summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorJames Zhao <jamesz@nvidia.com>2013-06-07 15:51:20 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:34:23 -0700
commit09745b57d5f9b4cc57a9bc6ca0e428ec6e918446 (patch)
tree4a578eee4d62bb9947fa3e938e881cc969fe4ef2 /security
parentdac6c1c7844bdfbf901a1af37c6de467130dbfca (diff)
tlk: New API changes for tlk
- add new parameter passing support for variable number of parameter - some clean up of naming conventions Bug 1310292 Change-Id: Ie9669456682fe2b85eb79a3d9cb4cbac9eba8d54 Signed-off-by: James Zhao <jamesz@nvidia.com> Reviewed-on: http://git-master/r/239104 (cherry picked from commit da4ee985be76b4f02284510d2eb7e851fb50bc0b) Reviewed-on: http://git-master/r/249870 Reviewed-by: Varun Wadekar <vwadekar@nvidia.com> Tested-by: Varun Wadekar <vwadekar@nvidia.com> Tested-by: Aaron Gamble <jgamble@nvidia.com>
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig2
-rw-r--r--security/Makefile4
-rw-r--r--security/nv_tee_driver/Kconfig8
-rw-r--r--security/nv_tee_driver/tee_client_api.h115
-rw-r--r--security/nv_tee_driver/tee_comms.c455
-rw-r--r--security/nv_tee_driver/tee_device.c364
-rw-r--r--security/nv_tee_driver/tee_protocol.h216
-rw-r--r--security/nv_tee_driver/tee_types.h109
-rw-r--r--security/tlk_driver/Kconfig7
-rw-r--r--security/tlk_driver/Makefile (renamed from security/nv_tee_driver/Makefile)18
-rw-r--r--security/tlk_driver/ote_comms.c372
-rw-r--r--security/tlk_driver/ote_device.c456
-rw-r--r--security/tlk_driver/ote_fs.c (renamed from security/nv_tee_driver/tee_fs.c)139
-rw-r--r--security/tlk_driver/ote_irq.S (renamed from security/nv_tee_driver/tee_irq.S)6
-rw-r--r--security/tlk_driver/ote_protocol.h202
-rw-r--r--security/tlk_driver/ote_types.h79
16 files changed, 1194 insertions, 1358 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 48c38202d998..60738cb04caa 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -122,7 +122,7 @@ source security/smack/Kconfig
source security/tomoyo/Kconfig
source security/apparmor/Kconfig
source security/tf_driver/Kconfig
-source security/nv_tee_driver/Kconfig
+source security/tlk_driver/Kconfig
source security/yama/Kconfig
source security/integrity/Kconfig
diff --git a/security/Makefile b/security/Makefile
index 219dc9e71e9c..6e5b56784cf7 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -9,7 +9,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
subdir-$(CONFIG_TRUSTED_FOUNDATIONS) += tf_driver
subdir-$(CONFIG_SECURITY_YAMA) += yama
-subdir-$(CONFIG_TRUSTED_LITTLE_KERNEL) += nv_tee_driver
+subdir-$(CONFIG_TRUSTED_LITTLE_KERNEL) += tlk_driver
# always enable default capabilities
obj-y += commoncap.o
@@ -27,7 +27,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += tf_driver/built-in.o
-obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += nv_tee_driver/built-in.o
+obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += tlk_driver/built-in.o
# Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity
diff --git a/security/nv_tee_driver/Kconfig b/security/nv_tee_driver/Kconfig
deleted file mode 100644
index ad74e591062b..000000000000
--- a/security/nv_tee_driver/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config TRUSTED_LITTLE_KERNEL
- bool "Enable NVIDIA Trusted Execution Environment driver"
- select TEGRA_USE_SECURE_KERNEL
- help
- This option adds kernel support for communication with the NVIDIA
- secure kernel.
- If you are unsure how to answer this question, answer N.
-
diff --git a/security/nv_tee_driver/tee_client_api.h b/security/nv_tee_driver/tee_client_api.h
deleted file mode 100644
index 0f0eed2275db..000000000000
--- a/security/nv_tee_driver/tee_client_api.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- */
-
-/*
- * This header file corresponds to V1.0_c of the GlobalPlatform
- * TEE Client API Specification
- */
-
-#ifndef __TEE_CLIENT_API_H__
-#define __TEE_CLIENT_API_H__
-
-#define TEEC_Result uint32_t;
-
-#define TEEC_PARAM_TYPES(t0, t1, t2, t3) \
- ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12))
-#define TEEC_PARAM_TYPE_GET(t, i) (((t) >> (i*4)) & 0xF)
-
-/*
- * Implementation dependent data types
- */
-
-struct TEEC_Context_Imp {
- uint32_t context_id;
-};
-
-struct TEEC_Session_Imp {
- uint32_t context_id;
- uint32_t session_id;
-};
-
-struct TEEC_Operation_Imp {
- uint32_t context_id;
- uint32_t session_id;
-};
-
-struct TEEC_SharedMemory_Imp {
- uint32_t context_id;
- uint32_t session_id;
- uint32_t alloc_state;
-};
-
-/*
- * Type definitions
- */
-
-struct TEEC_Context {
- struct TEEC_Context_Imp imp;
-};
-
-struct TEEC_Session {
- struct TEEC_Session_Imp imp;
-};
-
-struct TEEC_SharedMemory {
- void *buffer;
- size_t size;
- uint32_t flags;
- struct TEEC_SharedMemory_Imp imp;
-};
-
-union TEEC_Param {
- struct {
- void *buffer;
- size_t size;
- } tmpref;
- struct {
- struct TEEC_SharedMemory *parent;
- size_t size;
- size_t offset;
- } memref;
- struct {
- uint32_t a;
- uint32_t b;
- } value;
-};
-
-struct TEEC_Operation {
- uint32_t started;
- uint32_t paramTypes;
- union TEEC_Param params[4];
-};
-
-struct TEEC_UUID {
- uint32_t time_low;
- uint16_t time_mid;
- uint16_t time_hi_and_version;
- uint8_t clock_seq_and_node[8];
-};
-
-#define TEEC_MAX_FILE_NAME_LEN 64
-
-typedef enum {
- TEEC_FILE_REQ_READ = 0,
- TEEC_FILE_REQ_WRITE = 1,
- TEEC_FILE_REQ_DELETE = 2,
- TEEC_FILE_REQ_SIZE = 3,
-} TEEC_FileReqType;
-
-typedef struct {
- char name[TEEC_MAX_FILE_NAME_LEN];
- TEEC_FileReqType type;
- void *user_data_buf;
- void *kern_data_buf;
- unsigned long data_len;
- unsigned long result;
- int error;
-} TEEC_FileReq;
-
-struct tee_file_req_node {
- struct list_head node;
- TEEC_FileReq *req;
-};
-
-#endif
diff --git a/security/nv_tee_driver/tee_comms.c b/security/nv_tee_driver/tee_comms.c
deleted file mode 100644
index 81013894028d..000000000000
--- a/security/nv_tee_driver/tee_comms.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/printk.h>
-#include <linux/ioctl.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-#include "tee_types.h"
-#include "tee_protocol.h"
-
-bool verbose_smc;
-core_param(verbose_smc, verbose_smc, bool, 0644);
-
-#define SET_RESULT(req, r, ro) { req->result = r; req->result_origin = ro; }
-
-#define TEE_PARAM_COUNT 4
-
-static int tee_device_set_request_params(struct tee_request *request,
- struct TEEC_Operation *operation)
-{
- struct tee_cmd_param *param = &request->cmd_param;
- uint32_t i, type;
-
- param->param_types = operation->paramTypes;
- for (i = 0; i < TEE_PARAM_COUNT; i++) {
- type = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
- switch (type) {
- case TEEC_PARAM_TYPE_NONE:
- break;
- case TEEC_PARAM_TYPE_VALUE_INPUT:
- case TEEC_PARAM_TYPE_VALUE_OUTPUT:
- case TEEC_PARAM_TYPE_VALUE_INOUT:
- memcpy(&param->params[i].value,
- &operation->params[i].value,
- sizeof(union tee_param));
- break;
- case TEEC_PARAM_TYPE_MEMREF_INPUT:
- case TEEC_PARAM_TYPE_MEMREF_OUTPUT:
- case TEEC_PARAM_TYPE_MEMREF_INOUT:
- memcpy(&param->params[i].memref,
- &operation->params[i].tmpref,
- sizeof(union tee_param));
- break;
- default:
- return TEEC_ERROR_BAD_PARAMETERS;
- }
- }
- return TEEC_SUCCESS;
-}
-
-static int tee_device_get_answer_params(struct TEEC_Operation *operation,
- struct tee_request *request)
-{
- struct tee_cmd_param *param = &request->cmd_param;
- uint32_t i, type;
-
- param->param_types = operation->paramTypes;
- for (i = 0; i < TEE_PARAM_COUNT; i++) {
- type = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
- switch (type) {
- case TEEC_PARAM_TYPE_NONE:
- break;
- case TEEC_PARAM_TYPE_VALUE_INPUT:
- case TEEC_PARAM_TYPE_VALUE_OUTPUT:
- case TEEC_PARAM_TYPE_VALUE_INOUT:
- memcpy(&operation->params[i].value,
- &param->params[i].value,
- sizeof(union tee_param));
- break;
- case TEEC_PARAM_TYPE_MEMREF_INPUT:
- case TEEC_PARAM_TYPE_MEMREF_OUTPUT:
- case TEEC_PARAM_TYPE_MEMREF_INOUT:
- memcpy(&operation->params[i].tmpref,
- &param->params[i].memref,
- sizeof(union tee_param));
- break;
- default:
- return TEEC_ERROR_BAD_PARAMETERS;
- }
- }
- return TEEC_SUCCESS;
-}
-
-static int tee_pin_user_pages(void *buffer, size_t size,
- unsigned long *pages_ptr)
-{
- int ret = 0;
- unsigned int nr_pages;
- struct page **pages = NULL;
-
- nr_pages = (((unsigned int)buffer & (PAGE_SIZE - 1)) +
- (size + PAGE_SIZE - 1)) >> PAGE_SHIFT;
-
- pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
-
- down_read(&current->mm->mmap_sem);
- ret = get_user_pages(current, current->mm, (unsigned long)buffer,
- nr_pages, WRITE, 0, pages, NULL);
- up_read(&current->mm->mmap_sem);
-
- *pages_ptr = (unsigned long) pages;
-
- return ret;
-}
-
-static struct nv_shmem_desc *tee_add_shmem_desc(void *buffer, size_t size,
- unsigned int nr_pages, struct page **pages,
- struct nv_tee_context *context)
-{
- struct nv_shmem_desc *shmem_desc = NULL;
- shmem_desc = kzalloc(
- sizeof(struct nv_shmem_desc),
- GFP_KERNEL);
- if (shmem_desc) {
- INIT_LIST_HEAD(&(shmem_desc->list));
- shmem_desc->buffer = buffer;
- shmem_desc->size = size;
- shmem_desc->nr_pages = nr_pages;
- shmem_desc->pages = pages;
- list_add_tail(&shmem_desc->list, &(context->shmem_alloc_list));
- }
-
- return shmem_desc;
-}
-
-static int tee_pin_mem_buffers(void *buffer, size_t size,
- struct nv_tee_context *context)
-{
-
- unsigned long pages = 0;
- struct nv_shmem_desc *shmem_desc = NULL;
- int ret = 0, nr_pages = 0;
-
- nr_pages = tee_pin_user_pages(buffer, size, &pages);
- if (nr_pages <= 0) {
- pr_err("tee_pin_mem_buffers: tee_pin_user_pages Failed\n");
- ret = TEEC_ERROR_OUT_OF_MEMORY;
- goto error;
- }
-
- shmem_desc = tee_add_shmem_desc(buffer, size,
- nr_pages, (struct page **)pages, context);
- if (!shmem_desc) {
- pr_err("tee_pin_mem_buffers: tee_add_shmem_desc Failed\n");
- ret = TEEC_ERROR_OUT_OF_MEMORY;
- goto error;
- }
-
- return TEEC_SUCCESS;
-error:
- return ret;
-}
-
-static int tee_setup_temp_buffers(struct TEEC_Operation *oper,
- struct nv_tee_context *context)
-{
- uint32_t i, type;
- int ret = TEEC_SUCCESS;
-
- for (i = 0; i < TEE_PARAM_COUNT; i++) {
- type = TEEC_PARAM_TYPE_GET(oper->paramTypes, i);
- switch (type) {
- case TEEC_PARAM_TYPE_NONE:
- case TEEC_PARAM_TYPE_VALUE_INPUT:
- case TEEC_PARAM_TYPE_VALUE_OUTPUT:
- case TEEC_PARAM_TYPE_VALUE_INOUT:
- break;
- case TEEC_PARAM_TYPE_MEMREF_INPUT:
- case TEEC_PARAM_TYPE_MEMREF_OUTPUT:
- case TEEC_PARAM_TYPE_MEMREF_INOUT:
- ret = tee_pin_mem_buffers(
- oper->params[i].tmpref.buffer,
- oper->params[i].tmpref.size,
- context);
- if (ret < 0) {
- pr_err("tee_pin_mem_buffers failed with err (%d)\n",
- ret);
- ret = TEEC_ERROR_BAD_PARAMETERS;
- break;
- }
- break;
- default:
- pr_err("tee_pin_mem_buffers: TEEC_ERROR_BAD_PARAMETERS\n");
- ret = TEEC_ERROR_BAD_PARAMETERS;
- break;
- }
- }
- return ret;
-}
-
-static void tee_del_shmem_desc(void *buffer, struct nv_tee_context *context)
-{
- struct nv_shmem_desc *shmem_desc, *tmp_shmem_desc;
- int i;
-
- list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
- &(context->shmem_alloc_list), list) {
- if (shmem_desc->buffer == buffer) {
- list_del(&shmem_desc->list);
- for (i = 0; i < shmem_desc->nr_pages; i++)
- page_cache_release(shmem_desc->pages[i]);
- kfree(shmem_desc->pages);
- kfree(shmem_desc);
- }
- }
-}
-
-/*
- * Deregister previously initialized shared memory
- */
-void tee_unregister_memory(void *buffer,
- struct nv_tee_context *context)
-{
- if (!(list_empty(&(context->shmem_alloc_list))))
- tee_del_shmem_desc(buffer, context);
- else
- pr_err("No buffers to unpin\n");
-}
-
-static void tee_unpin_temp_buffers(struct TEEC_Operation *oper,
- struct nv_tee_context *context)
-{
- uint32_t i, type;
-
- for (i = 0; i < TEE_PARAM_COUNT; i++) {
- type = TEEC_PARAM_TYPE_GET(oper->paramTypes, i);
- switch (type) {
- case TEEC_PARAM_TYPE_NONE:
- case TEEC_PARAM_TYPE_VALUE_INPUT:
- case TEEC_PARAM_TYPE_VALUE_OUTPUT:
- case TEEC_PARAM_TYPE_VALUE_INOUT:
- break;
- case TEEC_PARAM_TYPE_MEMREF_INPUT:
- case TEEC_PARAM_TYPE_MEMREF_OUTPUT:
- case TEEC_PARAM_TYPE_MEMREF_INOUT:
- tee_unregister_memory(oper->params[i].tmpref.buffer,
- context);
- break;
- default:
- pr_err("tee_unpin_mem_buffers: TEEC_ERROR_BAD_PARAMETERS\n");
- break;
- }
- }
-}
-
-/*
- * Do an SMC call
- */
-static void do_smc(struct tee_request *request)
-{
- phys_addr_t smc_args = virt_to_phys(request);
- unsigned long regs[15];
-
-#ifdef CONFIG_SMP
- long ret;
- cpumask_t saved_cpu_mask;
- cpumask_t local_cpu_mask = CPU_MASK_NONE;
-
- cpu_set(0, local_cpu_mask);
- cpumask_copy(&saved_cpu_mask, tsk_cpus_allowed(current));
- ret = sched_setaffinity(0, &local_cpu_mask);
- if (ret != 0)
- pr_err("sched_setaffinity #1 -> 0x%lX", ret);
-#endif
-
- asm volatile (
- "mov r0, %0 \n"
- "stmia r0, {r4-r12} \n"
- "mov r0, %1 \n"
- "mov r1, %2 \n"
-#ifdef REQUIRES_SEC
- ".arch_extension sec \n"
-#endif
- "smc #0 \n"
- "mov r1, %0 \n"
- "ldmia r1, {r4-r12} \n"
- : : "r" (regs), "r" (request->type), "r" (smc_args)
- : "r0", "r1"
- );
-
-#ifdef CONFIG_SMP
- ret = sched_setaffinity(0, &saved_cpu_mask);
- if (ret != 0)
- pr_err("sched_setaffinity #2 -> 0x%lX", ret);
-#endif
-}
-
-/*
- * Do an 'empty' request just to get more pending answers.
- */
-static void get_more_answers(struct tee_request *request)
-{
- request->type = TMK_SMC_GET_MORE;
- /* rest of request ignored */
- do_smc(request);
-}
-
-/*
- * Open session SMC (TEEC_OpenSession)
- */
-void tee_open_session(struct tee_opensession *cmd,
- struct tee_request *request,
- struct nv_tee_context *context)
-{
- int ret;
-
- ret = tee_device_set_request_params(request, &cmd->operation);
- if (ret != TEEC_SUCCESS) {
- pr_err("tee_device_set_request_params failed\n");
- SET_RESULT(request, ret, TEEC_ORIGIN_API);
- return;
- }
-
- ret = tee_setup_temp_buffers(&cmd->operation, context);
- if (ret != TEEC_SUCCESS) {
- pr_err("tee_setup_temp_buffers failed err (0x%x)\n", ret);
- SET_RESULT(request, ret, TEEC_ORIGIN_API);
- return;
- }
-
- memcpy(&request->cmd_param.dest_uuid,
- &cmd->dest_uuid,
- sizeof(struct TEEC_UUID));
-
- pr_info("OPEN_CLIENT_SESSION: 0x%x 0x%x 0x%x 0x%x\n",
- request->cmd_param.dest_uuid[0],
- request->cmd_param.dest_uuid[1],
- request->cmd_param.dest_uuid[2],
- request->cmd_param.dest_uuid[3]);
-
- request->type = TMK_SMC_OPEN_SESSION;
-
- do_smc(request);
-
- tee_device_get_answer_params(&cmd->operation, request);
-
- tee_unpin_temp_buffers(&cmd->operation, context);
-}
-
-/*
- * Close session SMC (TEEC_CloseSession)
- */
-void tee_close_session(struct tee_closesession *cmd,
- struct tee_request *request)
-{
- request->type = TMK_SMC_CLOSE_SESSION;
- request->session_id = cmd->session_id;
-
- do_smc(request);
- if (request->result)
- pr_info("Error closing session: %08x\n", request->result);
-}
-
-/*
- * Register Shared Memory SMC (TEEC_RegisterSharedMemory)
- */
-void tee_register_memory(struct tee_sharedmem *cmd, struct tee_request *request,
- struct nv_tee_context *context)
-{
- int ret = 0;
-
- request->type = TMK_SMC_REG_SHARED_MEM;
- request->session_id = cmd->session_id;
-
- request->cmd_param.param_types = cmd->memref.flags;
- request->cmd_param.params[0].memref.buffer = cmd->memref.buffer;
- request->cmd_param.params[0].memref.size = cmd->memref.size;
-
- ret = tee_pin_mem_buffers(cmd->memref.buffer, cmd->memref.size,
- context);
- if (ret != TEEC_SUCCESS) {
- SET_RESULT(request, ret, TEEC_ORIGIN_API);
- return;
- }
-
- do_smc(request);
-}
-
-/*
- * Invoke Command SMC (TEEC_InvokeCommand)
- */
-void tee_invoke_command(struct tee_invokecmd *cmd,
- struct tee_request *request,
- struct nv_tee_context *context)
-{
- int ret = TEEC_SUCCESS;
-
- ret = tee_device_set_request_params(request, &cmd->operation);
- if (ret != TEEC_SUCCESS) {
- pr_err("tee_device_set_request_params failed\n");
- SET_RESULT(request, ret, TEEC_ORIGIN_API);
- return;
- }
-
- ret = tee_setup_temp_buffers(&cmd->operation, context);
- if (ret != TEEC_SUCCESS) {
- pr_err("tee_setup_temp_buffers failed err (0x%x)\n", ret);
- SET_RESULT(request, ret, TEEC_ORIGIN_API);
- return;
- }
-
- request->type = TMK_SMC_INVOKE_CMD;
- request->session_id = cmd->session_id;
- request->command_id = cmd->command_id;
-
- do_smc(request);
-
- tee_device_get_answer_params(&cmd->operation, request);
-
- tee_unpin_temp_buffers(&cmd->operation, context);
-}
-
-static int __init nv_tee_register_irq_handler(void)
-{
- asm volatile (
- "mov r1, %0\n"
- "movw r0, #0x1FF0\n"
- "movt r0, #0xFFFF\n"
-#ifdef REQUIRES_SEC
- ".arch_extension sec\n"
-#endif
- "smc #0\n"
- "cpsie i\n"
- : : "r" (nv_tee_irq_handler)
- : "r0", "r1", "r13", "r14"
- );
-
- return 0;
-}
-
-arch_initcall(nv_tee_register_irq_handler);
diff --git a/security/nv_tee_driver/tee_device.c b/security/nv_tee_driver/tee_device.c
deleted file mode 100644
index 57a5f5fa0c3e..000000000000
--- a/security/nv_tee_driver/tee_device.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/printk.h>
-#include <linux/ioctl.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <asm/cacheflush.h>
-#include <asm/outercache.h>
-#include <linux/list.h>
-
-#include "tee_protocol.h"
-#include "tee_types.h"
-
-#define SET_ANSWER(a, r, ro) { a.result = r; a.return_origin = ro; }
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/nvsecurity.h>
-
-u32 notrace tegra_read_cycle(void)
-{
- u32 cycle_count;
-
- asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(cycle_count));
-
- return cycle_count;
-}
-
-struct nv_device tee_nv_dev;
-
-/*
- * The maximum number of outstanding command requests.
- */
-#define NV_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct tee_request))
-
-static int tee_create_free_cmd_list(struct nv_device *dev)
-{
- struct page *tee_cmd_page;
- int cmd_desc_count = 0, ret = 0;
- struct nv_cmd_param_desc *param_desc;
-
- tee_cmd_page = alloc_pages(GFP_KERNEL, 1);
- if (!tee_cmd_page) {
- ret = -ENOMEM;
- goto error;
- }
- set_pages_array_uc(&tee_cmd_page, 1);
- dev->param_addr = (unsigned long) page_address(tee_cmd_page);
-
- for (cmd_desc_count = 0;
- cmd_desc_count < NV_CMD_DESC_MAX; cmd_desc_count++) {
-
- param_desc = kzalloc(
- sizeof(struct nv_cmd_param_desc),
- GFP_KERNEL);
- if (param_desc == NULL) {
- pr_err("Failed to allocate cmd param descriptor\n");
- ret = -ENOMEM;
- goto error;
- }
- param_desc->param_addr =
- dev->param_addr +
- sizeof(struct tee_request) * cmd_desc_count;
- INIT_LIST_HEAD(&(param_desc->list));
-
- /*Add the cmd param descriptor to free list*/
- list_add_tail(&param_desc->list, &(dev->free_cmd_list));
- }
-error:
- return ret;
-
-}
-
-static struct nv_cmd_param_desc *tee_get_free_cmd_desc(struct nv_device *nv_dev)
-{
- struct nv_cmd_param_desc *cmd_desc = NULL;
-
- if (!(list_empty(&(nv_dev->free_cmd_list)))) {
- cmd_desc = list_first_entry(&(nv_dev->free_cmd_list),
- struct nv_cmd_param_desc, list);
- list_del(&(cmd_desc->list));
- list_add_tail(&cmd_desc->list, &(nv_dev->used_cmd_list));
- }
- return cmd_desc;
-}
-
-static void tee_put_used_cmd_desc(struct nv_device *nv_dev,
- struct nv_cmd_param_desc *cmd_desc)
-{
- struct nv_cmd_param_desc *param_desc, *tmp_param_desc;
-
- if (cmd_desc) {
- list_for_each_entry_safe(param_desc, tmp_param_desc,
- &(nv_dev->used_cmd_list), list) {
- if (cmd_desc->param_addr ==
- param_desc->param_addr) {
- list_del(&param_desc->list);
- list_add_tail(&param_desc->list,
- &(nv_dev->free_cmd_list));
- }
- }
- }
-}
-
-static void tee_print_cmd_list(struct nv_device *dev, int used_list)
-{
- struct nv_cmd_param_desc *param_desc;
-
- if (!used_list) {
- pr_info("Printing free cmd list\n");
- if (!(list_empty(&(dev->free_cmd_list)))) {
- list_for_each_entry(param_desc, &(dev->free_cmd_list),
- list)
- pr_info("Phys addr for cmd param desc (%X)\n",
- param_desc->param_addr);
- }
- } else {
- pr_info("Printing used cmd list\n");
- if (!(list_empty(&(dev->used_cmd_list)))) {
- list_for_each_entry(param_desc, &(dev->used_cmd_list),
- list)
- pr_info("Phys addr for cmd param desc (%X)\n",
- param_desc->param_addr);
- }
- }
-}
-
-static int tee_device_open(struct inode *inode, struct file *file)
-{
- struct nv_tee_context *context;
- int ret = 0;
-
- context = kzalloc(
- sizeof(struct nv_tee_context), GFP_KERNEL);
- if (!context) {
- ret = -ENOMEM;
- goto error;
- }
- context->dev = &tee_nv_dev;
- INIT_LIST_HEAD(&(context->shmem_alloc_list));
-
- file->private_data = context;
- return 0;
-error:
- return ret;
-}
-
-static int tee_device_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
- file->private_data = NULL;
- return 0;
-}
-
-static long tee_handle_trustedapp_ioctl(struct file *file, unsigned int ioctl_num,
- unsigned long ioctl_param)
-{
- long err = 0;
- union tee_cmd cmd;
- void *ptr_user_answer = NULL;
- struct tee_answer answer;
- struct tee_request *request;
- struct nv_cmd_param_desc *cmd_desc = NULL;
- struct nv_tee_context *context = file->private_data;
- struct nv_device *nv_dev = context->dev;
-
- if (copy_from_user(&cmd, (void __user *)ioctl_param,
- sizeof(union tee_cmd))) {
- pr_err("Failed to copy command request\n");
- err = -EFAULT;
- goto error;
- }
-
- memset(&answer, 0, sizeof(struct tee_answer));
- switch (ioctl_num) {
- case TEE_IOCTL_OPEN_CLIENT_SESSION:
- ptr_user_answer = (void *)cmd.opensession.answer;
-
- cmd_desc = tee_get_free_cmd_desc(nv_dev);
- if (!cmd_desc) {
- SET_ANSWER(answer,
- TEEC_ERROR_OUT_OF_MEMORY,
- TEEC_ORIGIN_COMMS);
- pr_err("failed to get cmd_desc\n");
- goto error;
- }
-
- request = (struct tee_request *)cmd_desc->param_addr;
- memset(request, 0, sizeof(struct tee_request));
-
- tee_open_session(&cmd.opensession, request, context);
-
- memcpy(answer.params, cmd.opensession.operation.params,
- sizeof(answer.params));
-
- SET_ANSWER(answer, request->result, request->result_origin);
- answer.session_id = request->session_id;
- break;
-
- case TEE_IOCTL_CLOSE_CLIENT_SESSION:
- ptr_user_answer = (void *)cmd.closesession.answer;
- cmd_desc = tee_get_free_cmd_desc(nv_dev);
- if (!cmd_desc) {
- SET_ANSWER(answer,
- TEEC_ERROR_OUT_OF_MEMORY,
- TEEC_ORIGIN_COMMS);
- pr_err("failed to get cmd_desc\n");
- goto error;
- }
-
- request = (struct tee_request *)cmd_desc->param_addr;
- memset(request, 0, sizeof(struct tee_request));
-
- /* close session cannot fail */
- tee_close_session(&cmd.closesession, request);
- break;
-
- case TEE_IOCTL_REGISTER_MEMORY:
- ptr_user_answer = (void *)cmd.sharedmem.answer;
- cmd_desc = tee_get_free_cmd_desc(nv_dev);
- if (!cmd_desc) {
- SET_ANSWER(answer,
- TEEC_ERROR_OUT_OF_MEMORY,
- TEEC_ORIGIN_COMMS);
- pr_err("failed to get cmd_desc\n");
- goto error;
- }
-
- request = (struct tee_request *)cmd_desc->param_addr;
- memset(request, 0, sizeof(request));
-
- tee_register_memory(&cmd.sharedmem, request, context);
-
- SET_ANSWER(answer, request->result, request->result_origin);
-
- break;
-
- case TEE_IOCTL_RELEASE_SHARED_MEM:
- tee_unregister_memory(cmd.release_shared_mem.buffer,
- context);
- break;
-
- case TEE_IOCTL_INVOKE_COMMAND:
- ptr_user_answer = (void *)cmd.invokecmd.answer;
- cmd_desc = tee_get_free_cmd_desc(nv_dev);
-
- if (!cmd_desc) {
- SET_ANSWER(answer,
- TEEC_ERROR_OUT_OF_MEMORY,
- TEEC_ORIGIN_COMMS);
- pr_err("failed to get cmd_desc\n");
- goto error;
- }
-
- request = (struct tee_request *)cmd_desc->param_addr;
- memset(request, 0, sizeof(struct tee_request));
-
- tee_invoke_command(&cmd.invokecmd, request, context);
-
- memcpy(answer.params, cmd.invokecmd.operation.params,
- sizeof(answer.params));
-
- SET_ANSWER(answer, request->result, request->result_origin);
- break;
-
- default:
- pr_err("Invalid IOCTL Cmd\n");
- err = -EINVAL;
- goto error;
- }
- if (ptr_user_answer && !err)
- if (copy_to_user(ptr_user_answer, &answer,
- sizeof(struct tee_answer))) {
- pr_err("Failed to copy answer\n");
- err = -EFAULT;
- }
-
-error:
- if (cmd_desc)
- tee_put_used_cmd_desc(nv_dev, cmd_desc);
- return err;
-}
-
-static long tee_device_ioctl(struct file *file, unsigned int ioctl_num,
- unsigned long ioctl_param)
-{
- int err;
-
- switch (ioctl_num) {
- case TEE_IOCTL_OPEN_CLIENT_SESSION:
- case TEE_IOCTL_CLOSE_CLIENT_SESSION:
- case TEE_IOCTL_REGISTER_MEMORY:
- case TEE_IOCTL_RELEASE_SHARED_MEM:
- case TEE_IOCTL_INVOKE_COMMAND:
- err = tee_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
- break;
-
- case TEE_IOCTL_FILE_NEW_REQ:
- case TEE_IOCTL_FILE_FILL_BUF:
- case TEE_IOCTL_FILE_REQ_COMPLETE:
- err = tee_handle_fs_ioctl(file, ioctl_num, ioctl_param);
- break;
-
- default:
- pr_err("%s: Invalid IOCTL (0x%lx) 0x%lx, %d\n", __func__,
- ioctl_num, TEE_IOCTL_FILE_NEW_REQ,
- sizeof(TEEC_FileReq));
- err = -EINVAL;
- }
-
- return err;
-}
-
-/*
- * tee_driver function definitions.
- */
-static const struct file_operations tegra_tee_device_fops = {
- .owner = THIS_MODULE,
- .open = tee_device_open,
- .release = tee_device_release,
- .unlocked_ioctl = tee_device_ioctl,
-};
-
-struct miscdevice tegra_tee_device = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "tee_device",
- .fops = &tegra_tee_device_fops,
-};
-
-static int __init nv_tee_init(void)
-{
- int ret;
-
- INIT_LIST_HEAD(&(tee_nv_dev.used_cmd_list));
- INIT_LIST_HEAD(&(tee_nv_dev.free_cmd_list));
-
- ret = tee_create_free_cmd_list(&tee_nv_dev);
- if (ret != 0)
- return ret;
-
- return misc_register(&tegra_tee_device);
-}
-
-module_init(nv_tee_init);
diff --git a/security/nv_tee_driver/tee_protocol.h b/security/nv_tee_driver/tee_protocol.h
deleted file mode 100644
index 2c6e71e3d7f3..000000000000
--- a/security/nv_tee_driver/tee_protocol.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef __NV_TEE_PROTOCOL_H
-#define __NV_TEE_PROTOCOL_H
-
-#include "tee_types.h"
-#include "tee_client_api.h"
-
-#define TEE_IOCTL_MAGIC_NUMBER ('t')
-#define TEE_IOCTL_OPEN_CLIENT_SESSION \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x10, union tee_cmd)
-#define TEE_IOCTL_CLOSE_CLIENT_SESSION \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x11, union tee_cmd)
-#define TEE_IOCTL_REGISTER_MEMORY \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x12, union tee_cmd)
-#define TEE_IOCTL_RELEASE_SHARED_MEM \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x13, struct TEEC_SharedMemory)
-#define TEE_IOCTL_INVOKE_COMMAND \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x14, union tee_cmd)
-#define TEE_IOCTL_REQ_CANCELLATION \
- _IOR(TEE_IOCTL_MAGIC_NUMBER, 0x15, union tee_cmd)
-#define TEE_IOCTL_FILE_NEW_REQ \
- _IOR(TEE_IOCTL_MAGIC_NUMBER, 0x16, TEEC_FileReq)
-#define TEE_IOCTL_FILE_FILL_BUF \
- _IOR(TEE_IOCTL_MAGIC_NUMBER, 0x17, TEEC_FileReq)
-#define TEE_IOCTL_FILE_REQ_COMPLETE \
- _IOWR(TEE_IOCTL_MAGIC_NUMBER, 0x18, TEEC_FileReq)
-
-#define TEE_IOCTL_MIN_NR _IOC_NR(TEE_IOCTL_OPEN_CLIENT_SESSION)
-#define TEE_IOCTL_MAX_NR _IOC_NR(TEE_IOCTL_FILE_REQ_COMPLETE)
-
-#define NV_CMD_DESC_MAX 120
-
-extern void nv_tee_irq_handler(void);
-
-struct nv_device {
- unsigned long param_addr;
- struct list_head used_cmd_list;
- struct list_head free_cmd_list;
-};
-
-struct nv_cmd_param_desc {
- unsigned long param_addr;
- struct list_head list;
-};
-
-struct nv_shmem_desc {
- struct list_head list;
- void *buffer;
- size_t size;
- unsigned int mem_type;
- struct page **pages;
- unsigned int nr_pages;
-};
-
-struct nv_tee_context {
- struct nv_device *dev;
- struct list_head shmem_alloc_list;
-};
-
-enum {
- /* Do a tee invoke */
- TMK_SMC_INVOKE_CMD = 0xFFFF1000,
- /* Get a pending answer without making new invokes */
- TMK_SMC_GET_MORE = 0xFFFF1001,
- /* Answer from secure side */
- TMK_SMC_ANSWER = 0xFFFF1002,
- /* No answers for now (secure side idle) */
- TMK_SMC_NO_ANSWER = 0xFFFF1003,
- /* Open Session */
- TMK_SMC_OPEN_SESSION = 0xFFFF1004,
- /* Close Session */
- TMK_SMC_CLOSE_SESSION = 0xFFFF1005,
- /* Alloc Shared Memory*/
- TMK_SMC_ALLOC_SHARED_MEM = 0xFFFF1006,
- /* Register Shared Memory*/
- TMK_SMC_REG_SHARED_MEM = 0xFFFF1007,
- /* Release Shared Memory*/
- TMK_SMC_RELEASE_SHARED_MEM = 0xFFFF1008,
-};
-
-union tee_param {
- struct {
- void *buffer;
- size_t size;
- } memref;
- struct {
- uint32_t a;
- uint32_t b;
- } value;
-};
-
-/*
- * structures for user app communication
- */
-
-/*
- * OpenSession
- */
-
-struct tee_opensession {
- struct TEEC_UUID dest_uuid;
- uint32_t login_types;
- uint32_t login_data;
- struct TEEC_Operation operation;
- uint32_t answer;
-};
-
-/*
- * CloseSession
- */
-struct tee_closesession {
- uint32_t session_id;
- uint32_t answer;
-};
-
-/*
- * Shared Memory request
- */
-struct tee_sharedmem {
- uint32_t session_id;
- uint32_t command_id;
- struct TEEC_SharedMemory memref;
- uint32_t answer;
-};
-
-/*
- * Invoke Command request
- */
-struct tee_invokecmd {
- uint32_t session_id;
- uint32_t command_id;
- struct TEEC_Operation operation;
- uint32_t answer;
-};
-
-/*
- * Request Cancellation request
- */
-struct tee_req_cancellation {
- uint32_t session_id;
- uint32_t command_id;
- struct TEEC_Operation operation;
- uint32_t answer;
-};
-
-union tee_cmd {
- struct tee_opensession opensession;
- struct tee_closesession closesession;
- struct tee_sharedmem sharedmem;
- struct TEEC_SharedMemory release_shared_mem;
- struct tee_invokecmd invokecmd;
- struct tee_req_cancellation cancellation;
-};
-
-struct tee_cmd_param {
- uint32_t param_types;
- union tee_param params[4];
- uint32_t dest_uuid[4];
-};
-
-struct tee_request {
- uint32_t type;
- uint32_t session_id;
- uint32_t command_id;
- struct tee_cmd_param cmd_param;
- uint32_t result;
- uint32_t result_origin;
-};
-
-struct tee_answer {
- uint32_t type;
- uint32_t result;
- uint32_t return_origin;
- uint32_t session_id;
- union TEEC_Param params[4];
-};
-
-void tee_open_session(struct tee_opensession *cmd,
- struct tee_request *request,
- struct nv_tee_context *context);
-
-void tee_close_session(struct tee_closesession *cmd,
- struct tee_request *request);
-
-void tee_register_memory(struct tee_sharedmem *cmd,
- struct tee_request *request,
- struct nv_tee_context *context);
-
-void tee_invoke_command(struct tee_invokecmd *cmd,
- struct tee_request *request,
- struct nv_tee_context *context);
-
-void tee_unregister_memory(void *buffer,
- struct nv_tee_context *context);
-
-int tee_handle_fs_ioctl(struct file * file, unsigned int ioctl_num,
- unsigned long ioctl_param);
-
-#endif
diff --git a/security/nv_tee_driver/tee_types.h b/security/nv_tee_driver/tee_types.h
deleted file mode 100644
index c1233f4eb47a..000000000000
--- a/security/nv_tee_driver/tee_types.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef __NV_TEE_TYPES_H__
-#define __NV_TEE_TYPES_H__
-
-/*
- * Return Codes
- */
-enum {
- TEEC_SUCCESS = 0,
- /* Non-specific cause */
- TEEC_ERROR_GENERIC = 0xFFFF0000,
- /* Access priviledge not sufficient */
- TEEC_ERROR_ACCESS_DENIED = 0xFFFF0001,
- /* The operation was cancelled */
- TEEC_ERROR_CANCEL = 0xFFFF0002,
- /* Concurrent accesses conflict */
- TEEC_ERROR_ACCESS_CONFLICT = 0xFFFF0003,
- /* Too much data for req was passed */
- TEEC_ERROR_EXCESS_DATA = 0xFFFF0004,
- /* Input data was of invalid format */
- TEEC_ERROR_BAD_FORMAT = 0xFFFF0005,
- /* Input parameters were invalid */
- TEEC_ERROR_BAD_PARAMETERS = 0xFFFF0006,
- /* Oper invalid in current state */
- TEEC_ERROR_BAD_STATE = 0xFFFF0007,
- /* The req data item not found */
- TEEC_ERROR_ITEM_NOT_FOUND = 0xFFFF0008,
- /* The req oper not implemented */
- TEEC_ERROR_NOT_IMPLEMENTED = 0xFFFF0009,
- /* The req oper not supported */
- TEEC_ERROR_NOT_SUPPORTED = 0xFFFF000A,
- /* Expected data was missing */
- TEEC_ERROR_NO_DATA = 0xFFFF000B,
- /* System ran out of resources */
- TEEC_ERROR_OUT_OF_MEMORY = 0xFFFF000C,
- /* The system is busy */
- TEEC_ERROR_BUSY = 0xFFFF000D,
- /* Communication failed */
- TEEC_ERROR_COMMUNICATION = 0xFFFF000E,
- /* A security fault was detected */
- TEEC_ERROR_SECURITY = 0xFFFF000F,
- /* The supplied buffer is too short */
- TEEC_ERROR_SHORT_BUFFER = 0xFFFF0010,
-};
-
-/*
- * Return Code origins
- */
-enum {
- TEEC_ORIGIN_API = 1,
- TEEC_ORIGIN_COMMS = 2,
- TEEC_ORIGIN_TEE = 3,
- TEEC_ORIGIN_TRUSTED_APP = 4,
-};
-
-/*
- * Shared Memory control flags
- */
-enum {
- TEEC_MEM_INPUT = 1,
- TEEC_MEM_OUTPUT = 2,
-};
-
-/*
- * Parameter types
- */
-enum {
- TEEC_PARAM_TYPE_NONE = 0x0,
- TEEC_PARAM_TYPE_VALUE_INPUT = 0x1,
- TEEC_PARAM_TYPE_VALUE_OUTPUT = 0x2,
- TEEC_PARAM_TYPE_VALUE_INOUT = 0x3,
- TEEC_PARAM_TYPE_MEMREF_INPUT = 0x5,
- TEEC_PARAM_TYPE_MEMREF_OUTPUT = 0x6,
- TEEC_PARAM_TYPE_MEMREF_INOUT = 0x7,
- TEEC_MEMREF_WHOLE = 0xC,
- TEEC_MEMREF_PARTIAL_INPUT = 0xD,
- TEEC_MEMREF_PARTIAL_OUTPUT = 0xE,
- TEEC_MEMREF_PARTIAL_INOUT = 0xF,
-};
-
-/*
- * Session Login Methods
- */
-enum {
- TEEC_LOGIN_PUBLIC = 0x0,
- TEEC_LOGIN_USER = 0x1,
- TEEC_LOGIC_GROUP = 0x2,
- TEEC_LOGIC_APPLICATION = 0x4,
- TEEC_LOGIC_USER_APPLICATION = 0x5,
- TEEC_LOGIC_GROUP_APPLICATION = 0x6,
-};
-#endif
diff --git a/security/tlk_driver/Kconfig b/security/tlk_driver/Kconfig
new file mode 100644
index 000000000000..240a3180d7a0
--- /dev/null
+++ b/security/tlk_driver/Kconfig
@@ -0,0 +1,7 @@
+config TRUSTED_LITTLE_KERNEL
+ bool "Enable Open Trusted Execution driver"
+ select TEGRA_USE_SECURE_KERNEL
+ help
+ This option adds kernel support for communication with the
+ Trusted LK secure OS monitor/runtime support.
+ If you are unsure how to answer this question, answer N.
diff --git a/security/nv_tee_driver/Makefile b/security/tlk_driver/Makefile
index 00b65f1eb0de..2fb6a24acc24 100644
--- a/security/nv_tee_driver/Makefile
+++ b/security/tlk_driver/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, NVIDIA Corporation.
+# Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,13 +17,13 @@
#
plus_sec := $(call as-instr,.arch_extension sec,+sec)
-AFLAGS_tee_irq.o :=-Wa,-march=armv7-a$(plus_sec)
-CFLAGS_tee_comms.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
-CFLAGS_tee_fs.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+AFLAGS_ote_irq.o :=-Wa,-march=armv7-a$(plus_sec)
+CFLAGS_ote_comms.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+CFLAGS_ote_fs.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
-nv_tee_driver-objs += tee_device.o
-nv_tee_driver-objs += tee_comms.o
-nv_tee_driver-objs += tee_fs.o
-nv_tee_driver-objs += tee_irq.o
+tlk_driver-objs += ote_device.o
+tlk_driver-objs += ote_comms.o
+tlk_driver-objs += ote_fs.o
+tlk_driver-objs += ote_irq.o
-obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += nv_tee_driver.o
+obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += tlk_driver.o
diff --git a/security/tlk_driver/ote_comms.c b/security/tlk_driver/ote_comms.c
new file mode 100644
index 000000000000..fc9744ad3766
--- /dev/null
+++ b/security/tlk_driver/ote_comms.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/atomic.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/printk.h>
+#include <linux/ioctl.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include "ote_protocol.h"
+
+bool verbose_smc;
+core_param(verbose_smc, verbose_smc, bool, 0644);
+
+#define SET_RESULT(req, r, ro) { req->result = r; req->result_origin = ro; }
+
+static int te_pin_user_pages(void *buffer, size_t size,
+ unsigned long *pages_ptr)
+{
+ int ret = 0;
+ unsigned int nr_pages;
+ struct page **pages = NULL;
+
+ nr_pages = (((unsigned int)buffer & (PAGE_SIZE - 1)) +
+ (size + PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+ pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, (unsigned long)buffer,
+ nr_pages, WRITE, 0, pages, NULL);
+ up_read(&current->mm->mmap_sem);
+
+ *pages_ptr = (unsigned long) pages;
+
+ return ret;
+}
+
+static struct te_shmem_desc *te_add_shmem_desc(void *buffer, size_t size,
+ unsigned int nr_pages, struct page **pages,
+ struct tlk_context *context)
+{
+ struct te_shmem_desc *shmem_desc = NULL;
+ shmem_desc = kzalloc(sizeof(struct te_shmem_desc), GFP_KERNEL);
+ if (shmem_desc) {
+ INIT_LIST_HEAD(&(shmem_desc->list));
+ shmem_desc->buffer = buffer;
+ shmem_desc->size = size;
+ shmem_desc->nr_pages = nr_pages;
+ shmem_desc->pages = pages;
+ list_add_tail(&shmem_desc->list, &(context->shmem_alloc_list));
+ }
+
+ return shmem_desc;
+}
+
+static int te_pin_mem_buffers(void *buffer, size_t size,
+ struct tlk_context *context)
+{
+
+ unsigned long pages = 0;
+ struct te_shmem_desc *shmem_desc = NULL;
+ int ret = 0, nr_pages = 0;
+
+ nr_pages = te_pin_user_pages(buffer, size, &pages);
+ if (nr_pages <= 0) {
+ pr_err("%s: te_pin_user_pages Failed\n", __func__);
+ ret = OTE_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ shmem_desc = te_add_shmem_desc(buffer, size,
+ nr_pages, (struct page **)pages, context);
+ if (!shmem_desc) {
+ pr_err("%s: te_add_shmem_desc Failed\n", __func__);
+ ret = OTE_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ return OTE_SUCCESS;
+error:
+ return ret;
+}
+
+static int te_setup_temp_buffers(struct te_request *request,
+ struct tlk_context *context)
+{
+ uint32_t i;
+ int ret = OTE_SUCCESS;
+ struct te_oper_param *params = request->params;
+
+ for (i = 0; i < request->params_size; i++) {
+ switch (params[i].type) {
+ case TE_PARAM_TYPE_NONE:
+ case TE_PARAM_TYPE_INT_RO:
+ case TE_PARAM_TYPE_INT_RW:
+ break;
+ case TE_PARAM_TYPE_MEM_RO:
+ case TE_PARAM_TYPE_MEM_RW:
+ ret = te_pin_mem_buffers(
+ params[i].u.Mem.base,
+ params[i].u.Mem.len,
+ context);
+ if (ret < 0) {
+ pr_err("%s failed with err (%d)\n",
+ __func__, ret);
+ ret = OTE_ERROR_BAD_PARAMETERS;
+ break;
+ }
+ break;
+ default:
+ pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
+ ret = OTE_ERROR_BAD_PARAMETERS;
+ break;
+ }
+ }
+ return ret;
+}
+
+static void te_del_shmem_desc(void *buffer, struct tlk_context *context)
+{
+ struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
+ int i;
+
+ list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
+ &(context->shmem_alloc_list), list) {
+ if (shmem_desc->buffer == buffer) {
+ list_del(&shmem_desc->list);
+ for (i = 0; i < shmem_desc->nr_pages; i++)
+ page_cache_release(shmem_desc->pages[i]);
+ kfree(shmem_desc->pages);
+ kfree(shmem_desc);
+ }
+ }
+}
+
+/*
+ * Deregister previously initialized shared memory
+ */
+void te_unregister_memory(void *buffer,
+ struct tlk_context *context)
+{
+ if (!(list_empty(&(context->shmem_alloc_list))))
+ te_del_shmem_desc(buffer, context);
+ else
+ pr_err("No buffers to unpin\n");
+}
+
+static void te_unpin_temp_buffers(struct te_request *request,
+ struct tlk_context *context)
+{
+ uint32_t i;
+ struct te_oper_param *params = request->params;
+
+ for (i = 0; i < request->params_size; i++) {
+ switch (params[i].type) {
+ case TE_PARAM_TYPE_NONE:
+ case TE_PARAM_TYPE_INT_RO:
+ case TE_PARAM_TYPE_INT_RW:
+ break;
+ case TE_PARAM_TYPE_MEM_RO:
+ case TE_PARAM_TYPE_MEM_RW:
+ te_unregister_memory(params[i].u.Mem.base, context);
+ break;
+ default:
+ pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
+ break;
+ }
+ }
+}
+
+uint32_t __naked tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2)
+{
+ register uint32_t r0 asm("r0") = arg0;
+ register uint32_t r1 asm("r1") = arg1;
+ register uint32_t r2 asm("r2") = arg2;
+
+ asm volatile(
+ __asmeq("%0", "r0")
+ __asmeq("%1", "r0")
+ __asmeq("%2", "r1")
+ __asmeq("%3", "r2")
+ "stmfd sp!, {r4-r12} @ save reg state\n"
+#ifdef REQUIRES_SEC
+ ".arch_extension sec\n"
+#endif
+ "smc #0 @ switch to secure world\n"
+ "ldmfd sp!, {r4-r12} @ restore saved regs\n"
+ "bx lr"
+ : "=r" (r0)
+ : "r" (r0), "r" (r1), "r" (r2)
+ );
+ return r0;
+}
+
+uint32_t __naked tlk_extended_smc(uint32_t *regs)
+{
+ register uint32_t r0 asm("r0") = (uint32_t)regs;
+
+ /* allows MAX_EXT_SMC_ARGS (r0-r11) to be passed in registers */
+ asm volatile(
+ __asmeq("%0", "r0")
+ "stmfd sp!, {r4-r12} @ save reg state\n"
+ "mov r12, r0 @ reg ptr to r12\n"
+ "ldmia r12, {r0-r11} @ load arg regs\n"
+#ifdef REQUIRES_SEC
+ ".arch_extension sec\n"
+#endif
+ "smc #0 @ switch to secure world\n"
+ "ldmfd sp!, {r4-r12} @ restore saved regs\n"
+ "bx lr"
+ : "=r" (r0)
+ : "r" (r0)
+ );
+ return r0;
+}
+
+/*
+ * Do an SMC call
+ */
+static void do_smc(struct te_request *request)
+{
+#ifdef CONFIG_SMP
+ cpumask_t saved_cpu_mask;
+#endif
+ phys_addr_t smc_args = virt_to_phys(request);
+ phys_addr_t smc_params = 0;
+
+ if (request->params)
+ smc_params = virt_to_phys(request->params);
+
+#ifdef CONFIG_SMP
+{
+ long ret;
+ cpumask_t local_cpu_mask = CPU_MASK_NONE;
+
+ cpu_set(0, local_cpu_mask);
+ cpumask_copy(&saved_cpu_mask, tsk_cpus_allowed(current));
+ ret = sched_setaffinity(0, &local_cpu_mask);
+ if (ret)
+ pr_err("sched_setaffinity #1 -> 0x%lX", ret);
+}
+#endif
+
+ tlk_generic_smc(request->type, smc_args, smc_params);
+
+#ifdef CONFIG_SMP
+{
+ long ret = sched_setaffinity(0, &saved_cpu_mask);
+ if (ret)
+ pr_err("sched_setaffinity #2 -> 0x%lX", ret);
+}
+#endif
+}
+
+/*
+ * Open session SMC (supporting client-based te_open_session() calls)
+ */
+void te_open_session(struct te_opensession *cmd,
+ struct te_request *request,
+ struct tlk_context *context)
+{
+ int ret;
+
+ ret = te_setup_temp_buffers(request, context);
+ if (ret != OTE_SUCCESS) {
+ pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
+ SET_RESULT(request, ret, OTE_ERROR_ORIGIN_API);
+ return;
+ }
+
+ memcpy(&request->dest_uuid,
+ &cmd->dest_uuid,
+ sizeof(struct te_service_id));
+
+ pr_info("OPEN_CLIENT_SESSION: 0x%x 0x%x 0x%x 0x%x\n",
+ request->dest_uuid[0],
+ request->dest_uuid[1],
+ request->dest_uuid[2],
+ request->dest_uuid[3]);
+
+ request->type = TE_SMC_OPEN_SESSION;
+
+ do_smc(request);
+
+ te_unpin_temp_buffers(request, context);
+}
+
+/*
+ * Close session SMC (supporting client-based te_close_session() calls)
+ */
+void te_close_session(struct te_closesession *cmd,
+ struct te_request *request)
+{
+ request->session_id = cmd->session_id;
+ request->type = TE_SMC_CLOSE_SESSION;
+
+ do_smc(request);
+ if (request->result)
+ pr_info("Error closing session: %08x\n", request->result);
+}
+
+/*
+ * Launch operation SMC (supporting client-based te_launch_operation() calls)
+ */
+void te_launch_operation(struct te_launchop *cmd,
+ struct te_request *request,
+ struct tlk_context *context)
+{
+ int ret;
+
+ ret = te_setup_temp_buffers(request, context);
+ if (ret != OTE_SUCCESS) {
+ pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
+ SET_RESULT(request, ret, OTE_ERROR_ORIGIN_API);
+ return;
+ }
+
+ request->session_id = cmd->session_id;
+ request->command_id = cmd->operation.command;
+ request->type = TE_SMC_LAUNCH_OPERATION;
+
+ do_smc(request);
+
+ te_unpin_temp_buffers(request, context);
+}
+
+static int __init tlk_register_irq_handler(void)
+{
+ tlk_generic_smc(0xFFFF1FF0, (unsigned int)tlk_irq_handler, 0);
+
+#if 0
+ asm volatile (
+ "mov r1, %0\n"
+ "movw r0, #0x1FF0\n"
+ "movt r0, #0xFFFF\n"
+#ifdef REQUIRES_SEC
+ ".arch_extension sec\n"
+#endif
+ "smc #0\n"
+ "cpsie i\n"
+ : : "r" (tlk_irq_handler)
+ : "r0", "r1", "r13", "r14"
+ );
+#endif
+
+ return 0;
+}
+
+arch_initcall(tlk_register_irq_handler);
diff --git a/security/tlk_driver/ote_device.c b/security/tlk_driver/ote_device.c
new file mode 100644
index 000000000000..44d8a09971d0
--- /dev/null
+++ b/security/tlk_driver/ote_device.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/atomic.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/printk.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+#include <linux/list.h>
+
+#include "ote_protocol.h"
+
+#define SET_ANSWER(a, r, ro) { a.result = r; a.return_origin = ro; }
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/nvsecurity.h>
+
+struct tlk_device tlk_dev;
+
+u32 notrace tegra_read_cycle(void)
+{
+ u32 cycle_count;
+
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(cycle_count));
+
+ return cycle_count;
+}
+
+/*
+ * The maximum number of outstanding command requests.
+ */
+#define TE_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct te_request))
+#define TE_PARAM_MAX (PAGE_SIZE / sizeof(struct te_oper_param))
+
+static int te_create_free_cmd_list(struct tlk_device *dev)
+{
+ struct page *te_cmd_pages;
+ int cmd_desc_count = 0, ret = 0;
+ struct te_cmd_req_desc *req_desc;
+ int bitmap_size;
+
+ te_cmd_pages = alloc_pages(GFP_KERNEL, get_count_order(2));
+ if (!te_cmd_pages) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ /* first 4KB page is request freelist, second is param freelist */
+ dev->req_addr = (unsigned long) page_address(te_cmd_pages);
+ dev->param_addr = (struct te_oper_param *)(dev->req_addr + PAGE_SIZE);
+ set_memory_uc(dev->req_addr, 2);
+
+ /* alloc param bitmap allocator */
+ bitmap_size = BITS_TO_LONGS(TE_PARAM_MAX) * sizeof(long);
+ dev->param_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+
+ for (cmd_desc_count = 0;
+ cmd_desc_count < TE_CMD_DESC_MAX; cmd_desc_count++) {
+
+ req_desc = kzalloc(sizeof(struct te_cmd_req_desc), GFP_KERNEL);
+ if (req_desc == NULL) {
+ pr_err("Failed to allocate cmd req descriptor\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+ req_desc->req_addr = dev->req_addr +
+ sizeof(struct te_request) * cmd_desc_count;
+ INIT_LIST_HEAD(&(req_desc->list));
+
+ /* Add the cmd param descriptor to free list */
+ list_add_tail(&req_desc->list, &(dev->free_cmd_list));
+ }
+error:
+ return ret;
+
+}
+
+static struct te_oper_param *te_get_free_params(struct tlk_device *dev,
+ unsigned int nparams)
+{
+ struct te_oper_param *params = NULL;
+ int idx, nbits;
+
+ if (nparams) {
+ nbits = get_count_order(nparams);
+ idx = bitmap_find_free_region(dev->param_bitmap,
+ TE_PARAM_MAX, nbits);
+ if (idx >= 0)
+ params = dev->param_addr + idx;
+ }
+ return params;
+}
+
+static void te_put_free_params(struct tlk_device *dev,
+ struct te_oper_param *params, uint32_t nparams)
+{
+ int idx, nbits;
+
+ idx = (params - dev->param_addr);
+ nbits = get_count_order(nparams);
+ bitmap_release_region(dev->param_bitmap, idx, nbits);
+}
+
+static struct te_cmd_req_desc *te_get_free_cmd_desc(struct tlk_device *dev)
+{
+ struct te_cmd_req_desc *cmd_desc = NULL;
+
+ if (!(list_empty(&(dev->free_cmd_list)))) {
+ cmd_desc = list_first_entry(&(dev->free_cmd_list),
+ struct te_cmd_req_desc, list);
+ list_del(&(cmd_desc->list));
+ list_add_tail(&cmd_desc->list, &(dev->used_cmd_list));
+ }
+ return cmd_desc;
+}
+
+static void te_put_used_cmd_desc(struct tlk_device *dev,
+ struct te_cmd_req_desc *cmd_desc)
+{
+ struct te_cmd_req_desc *param_desc, *tmp_param_desc;
+
+ if (cmd_desc) {
+ list_for_each_entry_safe(param_desc, tmp_param_desc,
+ &(dev->used_cmd_list), list) {
+ if (cmd_desc->req_addr == param_desc->req_addr) {
+ list_del(&param_desc->list);
+ list_add_tail(&param_desc->list,
+ &(dev->free_cmd_list));
+ }
+ }
+ }
+}
+
+static void __attribute__((unused)) te_print_cmd_list(
+ struct tlk_device *dev, int used_list)
+{
+ struct te_cmd_req_desc *param_desc;
+
+ if (!used_list) {
+ pr_info("Printing free cmd list\n");
+ if (!(list_empty(&(dev->free_cmd_list)))) {
+ list_for_each_entry(param_desc, &(dev->free_cmd_list),
+ list)
+ pr_info("Phys addr for cmd req desc (%lx)\n",
+ param_desc->req_addr);
+ }
+ } else {
+ pr_info("Printing used cmd list\n");
+ if (!(list_empty(&(dev->used_cmd_list)))) {
+ list_for_each_entry(param_desc, &(dev->used_cmd_list),
+ list)
+ pr_info("Phys addr for cmd req desc (%lx)\n",
+ param_desc->req_addr);
+ }
+ }
+}
+
+static int tlk_device_open(struct inode *inode, struct file *file)
+{
+ struct tlk_context *context;
+ int ret = 0;
+
+ context = kzalloc(sizeof(struct tlk_context), GFP_KERNEL);
+ if (!context) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ context->dev = &tlk_dev;
+ INIT_LIST_HEAD(&(context->shmem_alloc_list));
+
+ file->private_data = context;
+ return 0;
+error:
+ return ret;
+}
+
+static int tlk_device_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ file->private_data = NULL;
+ return 0;
+}
+
+static int copy_params_from_user(struct te_request *req,
+ struct te_operation *operation)
+{
+ struct te_oper_param *param_array;
+ struct te_oper_param *user_param;
+ uint32_t i;
+
+ if (operation->list_count == 0)
+ return 0;
+
+ param_array = req->params;
+ if (param_array == NULL) {
+ pr_err("param_array empty\n");
+ return 1;
+ }
+
+ user_param = operation->list_head;
+ for (i = 0; i < operation->list_count && user_param != NULL; i++) {
+ if (copy_from_user(param_array + i, user_param,
+ sizeof(struct te_oper_param))) {
+ pr_err("Failed to copy operation parameter:%d, %p, " \
+ "list_count: %d\n",
+ i, user_param, operation->list_count);
+ return 1;
+ }
+ user_param = param_array[i].next_ptr_user;
+ }
+ return 0;
+}
+
+static int copy_params_to_user(struct te_request *req,
+ struct te_operation *operation)
+{
+ struct te_oper_param *param_array;
+ struct te_oper_param *user_param;
+ uint32_t i;
+
+ if (operation->list_count == 0)
+ return 0;
+
+ param_array = req->params;
+ if (param_array == NULL) {
+ pr_err("param_array empty\n");
+ return 1;
+ }
+
+ user_param = operation->list_head;
+ for (i = 0; i < req->params_size; i++) {
+ if (copy_to_user(user_param, param_array + i,
+ sizeof(struct te_oper_param))) {
+ pr_err("Failed to copy back parameter:%d %p\n", i,
+ user_param);
+ return 1;
+ }
+ user_param = param_array[i].next_ptr_user;
+ }
+ return 0;
+}
+
+static long te_handle_trustedapp_ioctl(struct file *file,
+ unsigned int ioctl_num, unsigned long ioctl_param)
+{
+ long err = 0;
+ union te_cmd cmd;
+ void *ptr_user_answer = NULL;
+ struct te_operation *operation = NULL;
+ struct te_oper_param *params = NULL;
+ struct te_answer answer;
+ struct te_request *request;
+
+ struct te_cmd_req_desc *cmd_desc = NULL;
+ struct tlk_context *context = file->private_data;
+ struct tlk_device *dev = context->dev;
+
+ if (copy_from_user(&cmd, (void __user *)ioctl_param,
+ sizeof(union te_cmd))) {
+ pr_err("Failed to copy command request\n");
+ err = -EFAULT;
+ goto error;
+ }
+
+ memset(&answer, 0, sizeof(struct te_answer));
+
+ switch (ioctl_num) {
+ case TE_IOCTL_OPEN_CLIENT_SESSION:
+ operation = &cmd.opensession.operation;
+ ptr_user_answer = (void *)cmd.opensession.answer;
+
+ cmd_desc = te_get_free_cmd_desc(dev);
+ params = te_get_free_params(dev, operation->list_count);
+
+ if (!cmd_desc || (operation->list_count && !params)) {
+ SET_ANSWER(answer,
+ OTE_ERROR_OUT_OF_MEMORY,
+ OTE_ERROR_ORIGIN_COMMS);
+ pr_err("failed to get cmd_desc/params\n");
+ goto error;
+ }
+
+ request = (struct te_request *)cmd_desc->req_addr;
+ memset(request, 0, sizeof(struct te_request));
+
+ request->params = params;
+ request->params_size = operation->list_count;
+
+ if (copy_params_from_user(request, operation)) {
+ err = -EFAULT;
+ pr_info("failed to copy params from user\n");
+ goto error;
+ }
+
+ te_open_session(&cmd.opensession, request, context);
+
+ SET_ANSWER(answer, request->result, request->result_origin);
+ answer.session_id = request->session_id;
+ break;
+
+ case TE_IOCTL_CLOSE_CLIENT_SESSION:
+ ptr_user_answer = (void *)cmd.closesession.answer;
+ cmd_desc = te_get_free_cmd_desc(dev);
+ if (!cmd_desc) {
+ SET_ANSWER(answer,
+ OTE_ERROR_OUT_OF_MEMORY,
+ OTE_ERROR_ORIGIN_COMMS);
+ pr_err("failed to get cmd_desc\n");
+ goto error;
+ }
+
+ request = (struct te_request *)cmd_desc->req_addr;
+ memset(request, 0, sizeof(struct te_request));
+
+ /* close session cannot fail */
+ te_close_session(&cmd.closesession, request);
+ break;
+
+ case TE_IOCTL_LAUNCH_OPERATION:
+ operation = &cmd.launchop.operation;
+ ptr_user_answer = (void *)cmd.launchop.answer;
+
+ cmd_desc = te_get_free_cmd_desc(dev);
+ params = te_get_free_params(dev, operation->list_count);
+
+ if (!cmd_desc || (operation->list_count && !params)) {
+ SET_ANSWER(answer,
+ OTE_ERROR_OUT_OF_MEMORY,
+ OTE_ERROR_ORIGIN_COMMS);
+ pr_err("failed to get cmd_desc/params\n");
+ goto error;
+ }
+
+ request = (struct te_request *)cmd_desc->req_addr;
+ memset(request, 0, sizeof(struct te_request));
+
+ request->params = params;
+ request->params_size = operation->list_count;
+
+ if (copy_params_from_user(request, operation)) {
+ err = -EFAULT;
+ pr_info("failed to copy params from user\n");
+ goto error;
+ }
+
+ te_launch_operation(&cmd.launchop, request, context);
+
+ SET_ANSWER(answer, request->result, request->result_origin);
+ break;
+
+ default:
+ pr_err("Invalid IOCTL Cmd\n");
+ err = -EINVAL;
+ goto error;
+ }
+ if (ptr_user_answer && !err) {
+ if (copy_to_user(ptr_user_answer, &answer,
+ sizeof(struct te_answer))) {
+ pr_err("Failed to copy answer\n");
+ err = -EFAULT;
+ }
+ }
+ if (request->params && !err) {
+ if (copy_params_to_user(request, operation)) {
+ pr_err("Failed to copy return params\n");
+ err = -EFAULT;
+ }
+ }
+
+error:
+ if (cmd_desc)
+ te_put_used_cmd_desc(dev, cmd_desc);
+ if (params)
+ te_put_free_params(dev, params, operation->list_count);
+ return err;
+}
+
+static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
+ unsigned long ioctl_param)
+{
+ int err;
+
+ switch (ioctl_num) {
+ case TE_IOCTL_OPEN_CLIENT_SESSION:
+ case TE_IOCTL_CLOSE_CLIENT_SESSION:
+ case TE_IOCTL_LAUNCH_OPERATION:
+ err = te_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
+ break;
+
+ case TE_IOCTL_FILE_NEW_REQ:
+ case TE_IOCTL_FILE_FILL_BUF:
+ case TE_IOCTL_FILE_REQ_COMPLETE:
+ err = te_handle_fs_ioctl(file, ioctl_num, ioctl_param);
+ break;
+
+ default:
+ pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%x\n", __func__,
+ ioctl_num, _IOC_NR(ioctl_num), TE_IOCTL_MAX_NR);
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+/*
+ * tlk_driver function definitions.
+ */
+static const struct file_operations tlk_device_fops = {
+ .owner = THIS_MODULE,
+ .open = tlk_device_open,
+ .release = tlk_device_release,
+ .unlocked_ioctl = tlk_device_ioctl,
+};
+
+struct miscdevice tlk_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "tlk_device",
+ .fops = &tlk_device_fops,
+};
+
+static int __init tlk_init(void)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&(tlk_dev.used_cmd_list));
+ INIT_LIST_HEAD(&(tlk_dev.free_cmd_list));
+
+ ret = te_create_free_cmd_list(&tlk_dev);
+ if (ret != 0)
+ return ret;
+
+ return misc_register(&tlk_misc_device);
+}
+
+module_init(tlk_init);
diff --git a/security/nv_tee_driver/tee_fs.c b/security/tlk_driver/ote_fs.c
index a5dbdfdf6102..716d004f68bb 100644
--- a/security/nv_tee_driver/tee_fs.c
+++ b/security/tlk_driver/ote_fs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, NVIDIA Corporation.
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,69 +23,62 @@
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <linux/bitops.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
+#include "ote_protocol.h"
-#include "tee_protocol.h"
+#define TE_SHMEM_FNAME_SZ SZ_64
+#define TE_SHMEM_DATA_SZ SZ_128K
+#define TE_FS_READY_BIT 1
-#define TEE_SHMEM_FNAME_SZ SZ_64
-#define TEE_SHMEM_DATA_SZ SZ_128K
-
-#define TEE_FS_READY_BIT 1
+struct te_file_req_shmem {
+ char file_name[TE_SHMEM_FNAME_SZ];
+ char file_data[TE_SHMEM_DATA_SZ];
+};
-struct tee_shmem {
- char file_name[TEE_SHMEM_FNAME_SZ];
- char file_data[TEE_SHMEM_DATA_SZ];
+struct te_file_req_node {
+ struct list_head node;
+ struct te_file_req *req;
};
-struct list_head req_list;
-DECLARE_COMPLETION(req_ready);
-DECLARE_COMPLETION(req_complete);
+static struct list_head req_list;
+static DECLARE_COMPLETION(req_ready);
+static DECLARE_COMPLETION(req_complete);
static unsigned long secure_error;
static unsigned long fs_ready;
static void indicate_complete(unsigned long ret)
{
- asm volatile (
- "mov r1, %0 \n"
- "movw r0, #0x1FFF \n"
- "movt r0, #0xFFFF \n"
-#ifdef REQUIRES_SEC
- ".arch_extension sec \n"
-#endif
- "smc #0 \n"
- : : "r" (ret)
- : "r0", "r1"
- );
+ tlk_generic_smc(0xFFFF1FFF, ret, 0);
}
-int tee_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
+int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param)
{
- TEEC_FileReq new_req, *ptr_user_req = NULL;
- struct tee_file_req_node *req_node;
+ struct te_file_req new_req, *ptr_user_req = NULL;
+ struct te_file_req_node *req_node;
switch (ioctl_num) {
- case TEE_IOCTL_FILE_NEW_REQ: /* new request */
+ case TE_IOCTL_FILE_NEW_REQ: /* new request */
- ptr_user_req = (TEEC_FileReq *)ioctl_param;
+ ptr_user_req = (struct te_file_req *)ioctl_param;
set_freezable();
- set_bit(TEE_FS_READY_BIT, &fs_ready);
+ set_bit(TE_FS_READY_BIT, &fs_ready);
/* wait for a new request */
while (wait_for_completion_interruptible(&req_ready))
try_to_freeze();
/* dequeue new request from the secure world */
- req_node = list_first_entry(&req_list, struct tee_file_req_node,
+ req_node = list_first_entry(&req_list, struct te_file_req_node,
node);
/* populate request for the non-secure client */
if (req_node) {
if (copy_to_user(ptr_user_req, req_node->req,
- sizeof(TEEC_FileReq))) {
+ sizeof(struct te_file_req))) {
pr_err("copy_to_user failed for new request\n");
return -EFAULT;
}
@@ -99,15 +92,15 @@ int tee_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
break;
- case TEE_IOCTL_FILE_FILL_BUF: /* pass data to be written to the file */
+ case TE_IOCTL_FILE_FILL_BUF: /* pass data to be written to the file */
if (copy_from_user(&new_req, (void __user *)ioctl_param,
- sizeof(TEEC_FileReq))) {
+ sizeof(struct te_file_req))) {
pr_err("copy_from_user failed for request\n");
return -EFAULT;
}
- if (new_req.type != TEEC_FILE_REQ_WRITE)
+ if (new_req.type != OTE_FILE_REQ_WRITE)
return -EINVAL;
if (!new_req.kern_data_buf || !new_req.user_data_buf)
@@ -120,15 +113,15 @@ int tee_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
}
break;
- case TEE_IOCTL_FILE_REQ_COMPLETE: /* request complete */
+ case TE_IOCTL_FILE_REQ_COMPLETE: /* request complete */
if (copy_from_user(&new_req, (void __user *)ioctl_param,
- sizeof(TEEC_FileReq))) {
+ sizeof(struct te_file_req))) {
pr_err("copy_from_user failed for request\n");
return -EFAULT;
}
- if (new_req.type == TEEC_FILE_REQ_READ && !new_req.error) {
+ if (new_req.type == OTE_FILE_REQ_READ && !new_req.error) {
if (copy_from_user(new_req.kern_data_buf,
(void __user *)new_req.user_data_buf,
new_req.data_len)) {
@@ -138,7 +131,8 @@ int tee_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
}
/* get error code */
- secure_error = (new_req.error) ? TEEC_ERROR_NO_DATA : new_req.result;
+ secure_error = (new_req.error) ? OTE_ERROR_NO_DATA
+ : new_req.result;
/* signal the producer */
complete(&req_complete);
@@ -148,25 +142,25 @@ int tee_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
return 0;
}
-static void _tee_fs_file_operation(const char *name, void *buf, int len,
- TEEC_FileReqType type)
+static void _te_fs_file_operation(const char *name, void *buf, int len,
+ enum te_file_req_type type)
{
- TEEC_FileReq *new_req;
- struct tee_file_req_node *req_node;
+ struct te_file_req *new_req;
+ struct te_file_req_node *req_node;
- if (!test_and_clear_bit(TEE_FS_READY_BIT, &fs_ready)) {
+ if (!test_and_clear_bit(TE_FS_READY_BIT, &fs_ready)) {
pr_err("%s: daemon not loaded yet\n", __func__);
- secure_error = TEEC_ERROR_NO_DATA;
+ secure_error = OTE_ERROR_NO_DATA;
goto fail;
}
BUG_ON(!name);
- if (type == TEEC_FILE_REQ_READ || type == TEEC_FILE_REQ_WRITE)
+ if (type == OTE_FILE_REQ_READ || type == OTE_FILE_REQ_WRITE)
BUG_ON(!buf);
- /* allocate TEEC_FileReq structure */
- new_req = kzalloc(sizeof(TEEC_FileReq), GFP_KERNEL);
+ /* allocate te_file_req structure */
+ new_req = kzalloc(sizeof(struct te_file_req), GFP_KERNEL);
BUG_ON(!new_req);
/* prepare a new request */
@@ -177,7 +171,7 @@ static void _tee_fs_file_operation(const char *name, void *buf, int len,
new_req->kern_data_buf = buf;
new_req->error = 0;
- req_node = kzalloc(sizeof(struct tee_file_req_node), GFP_KERNEL);
+ req_node = kzalloc(sizeof(struct te_file_req_node), GFP_KERNEL);
BUG_ON(!req_node);
req_node->req = new_req;
@@ -200,29 +194,30 @@ fail:
indicate_complete(secure_error);
}
-void nv_tee_fread(const char *name, void *buf, int len)
+void tlk_fread(const char *name, void *buf, int len)
{
if (!buf)
- _tee_fs_file_operation(name, buf, len, TEEC_FILE_REQ_SIZE);
+ _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_SIZE);
else
- _tee_fs_file_operation(name, buf, len, TEEC_FILE_REQ_READ);
+ _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_READ);
}
-void nv_tee_fwrite(const char *name, void *buf, int len)
+void tlk_fwrite(const char *name, void *buf, int len)
{
- _tee_fs_file_operation(name, buf, len, TEEC_FILE_REQ_WRITE);
+ _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_WRITE);
}
-void nv_tee_fdelete(const char *name)
+void tlk_fdelete(const char *name)
{
- _tee_fs_file_operation(name, NULL, 0, TEEC_FILE_REQ_DELETE);
+ _te_fs_file_operation(name, NULL, 0, OTE_FILE_REQ_DELETE);
}
-static int __init nv_tee_fs_register_handlers(void)
+static int __init tlk_fs_register_handlers(void)
{
- struct tee_shmem *shmem_ptr;
+ struct te_file_req_shmem *shmem_ptr;
+ uint32_t smc_args[MAX_EXT_SMC_ARGS];
- shmem_ptr = kzalloc(sizeof(struct tee_shmem), GFP_KERNEL);
+ shmem_ptr = kzalloc(sizeof(struct te_file_req_shmem), GFP_KERNEL);
if (!shmem_ptr) {
pr_err("%s: no memory available for fs operations\n", __func__);
return -ENOMEM;
@@ -232,24 +227,16 @@ static int __init nv_tee_fs_register_handlers(void)
init_completion(&req_ready);
init_completion(&req_complete);
- asm volatile (
- "movw r0, #0x1FF2 \n"
- "movt r0, #0xFFFF \n"
- "mov r1, %0 \n"
- "mov r2, %1 \n"
- "mov r3, %2 \n"
- "mov r4, %3 \n"
- "mov r5, %4 \n"
-#ifdef REQUIRES_SEC
- ".arch_extension sec \n"
-#endif
- "smc #0 \n"
- : : "r" (nv_tee_fread), "r" (nv_tee_fwrite), "r" (nv_tee_fdelete),
- "r" (shmem_ptr->file_name), "r" (shmem_ptr->file_data)
- : "r0", "r1", "r2", "r3", "r4", "r13", "r14"
- );
+ smc_args[0] = 0xFFFF1FF2;
+ smc_args[1] = (uint32_t)tlk_fread;
+ smc_args[2] = (uint32_t)tlk_fwrite;
+ smc_args[3] = (uint32_t)tlk_fdelete;
+ smc_args[4] = (uint32_t)shmem_ptr->file_name;
+ smc_args[5] = (uint32_t)shmem_ptr->file_data;
+
+ tlk_extended_smc(smc_args);
return 0;
}
-arch_initcall(nv_tee_fs_register_handlers);
+arch_initcall(tlk_fs_register_handlers);
diff --git a/security/nv_tee_driver/tee_irq.S b/security/tlk_driver/ote_irq.S
index 4e913cb24c03..7bfda8861108 100644
--- a/security/nv_tee_driver/tee_irq.S
+++ b/security/tlk_driver/ote_irq.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, NVIDIA Corporation.
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
#include <linux/linkage.h>
#include <linux/init.h>
-ENTRY(nv_tee_irq_handler)
+ENTRY(tlk_irq_handler)
movw r0, #0x1FF1
movt r0, #0xFFFF
smc #0
-ENDPROC(nv_tee_irq_handler)
+ENDPROC(tlk_irq_handler)
diff --git a/security/tlk_driver/ote_protocol.h b/security/tlk_driver/ote_protocol.h
new file mode 100644
index 000000000000..79224e1c3669
--- /dev/null
+++ b/security/tlk_driver/ote_protocol.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OTE_PROTOCOL_H__
+#define __OTE_PROTOCOL_H__
+
+#include "ote_types.h"
+
+#define TE_IOCTL_MAGIC_NUMBER ('t')
+#define TE_IOCTL_OPEN_CLIENT_SESSION \
+ _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x10, union te_cmd)
+#define TE_IOCTL_CLOSE_CLIENT_SESSION \
+ _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x11, union te_cmd)
+#define TE_IOCTL_LAUNCH_OPERATION \
+ _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd)
+#define TE_IOCTL_FILE_NEW_REQ \
+ _IOR(TE_IOCTL_MAGIC_NUMBER, 0x16, struct te_file_req)
+#define TE_IOCTL_FILE_FILL_BUF \
+ _IOR(TE_IOCTL_MAGIC_NUMBER, 0x17, struct te_file_req)
+#define TE_IOCTL_FILE_REQ_COMPLETE \
+ _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x18, struct te_file_req)
+
+#define TE_IOCTL_MIN_NR _IOC_NR(TE_IOCTL_OPEN_CLIENT_SESSION)
+#define TE_IOCTL_MAX_NR _IOC_NR(TE_IOCTL_FILE_REQ_COMPLETE)
+
+#define MAX_EXT_SMC_ARGS 12
+
+extern uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2);
+extern uint32_t tlk_extended_smc(uint32_t *args);
+extern void tlk_irq_handler(void);
+
+struct tlk_device {
+ unsigned long req_addr;
+ struct te_oper_param *param_addr;
+ unsigned long *param_bitmap;
+
+ struct list_head used_cmd_list;
+ struct list_head free_cmd_list;
+};
+
+struct te_cmd_req_desc {
+ unsigned long req_addr;
+ struct list_head list;
+};
+
+struct te_shmem_desc {
+ struct list_head list;
+ void *buffer;
+ size_t size;
+ unsigned int mem_type;
+ struct page **pages;
+ unsigned int nr_pages;
+};
+
+struct tlk_context {
+ struct tlk_device *dev;
+ struct list_head shmem_alloc_list;
+};
+
+enum {
+ TE_SMC_OPEN_SESSION = 0xFFFF1004,
+ TE_SMC_CLOSE_SESSION = 0xFFFF1005,
+ TE_SMC_LAUNCH_OPERATION = 0xFFFF1000,
+};
+
+enum {
+ TE_PARAM_TYPE_NONE = 0,
+ TE_PARAM_TYPE_INT_RO = 1,
+ TE_PARAM_TYPE_INT_RW = 2,
+ TE_PARAM_TYPE_MEM_RO = 3,
+ TE_PARAM_TYPE_MEM_RW = 4,
+};
+
+struct te_oper_param {
+ uint32_t index;
+ uint32_t type;
+ union {
+ struct {
+ uint32_t val;
+ } Int;
+ struct {
+ void *base;
+ uint32_t len;
+ } Mem;
+ } u;
+ void *next_ptr_user;
+};
+
+struct te_operation {
+ uint32_t command;
+ struct te_oper_param *list_head;
+ /* Maintain a pointer to tail of list to easily add new param node */
+ struct te_oper_param *list_tail;
+ uint32_t list_count;
+ uint32_t status;
+ uint32_t iterface_side;
+};
+
+struct te_service_id {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_and_node[8];
+};
+
+/*
+ * OpenSession
+ */
+struct te_opensession {
+ struct te_service_id dest_uuid;
+ struct te_operation operation;
+ uint32_t answer;
+};
+
+/*
+ * CloseSession
+ */
+struct te_closesession {
+ uint32_t session_id;
+ uint32_t answer;
+};
+
+/*
+ * LaunchOperation
+ */
+struct te_launchop {
+ uint32_t session_id;
+ struct te_operation operation;
+ uint32_t answer;
+};
+
+union te_cmd {
+ struct te_opensession opensession;
+ struct te_closesession closesession;
+ struct te_launchop launchop;
+};
+
+struct te_request {
+ uint32_t type;
+ uint32_t session_id;
+ uint32_t command_id;
+ struct te_oper_param *params;
+ uint32_t params_size;
+ uint32_t dest_uuid[4];
+ uint32_t result;
+ uint32_t result_origin;
+};
+
+struct te_answer {
+ uint32_t result;
+ uint32_t session_id;
+ uint32_t return_origin;
+};
+
+void te_open_session(struct te_opensession *cmd,
+ struct te_request *request,
+ struct tlk_context *context);
+
+void te_close_session(struct te_closesession *cmd,
+ struct te_request *request);
+
+void te_launch_operation(struct te_launchop *cmd,
+ struct te_request *request,
+ struct tlk_context *context);
+
+#define TE_MAX_FILE_NAME_LEN 64
+
+enum te_file_req_type {
+ OTE_FILE_REQ_READ = 0,
+ OTE_FILE_REQ_WRITE = 1,
+ OTE_FILE_REQ_DELETE = 2,
+ OTE_FILE_REQ_SIZE = 3,
+};
+
+struct te_file_req {
+ char name[TE_MAX_FILE_NAME_LEN];
+ enum te_file_req_type type;
+ void *user_data_buf;
+ void *kern_data_buf;
+ unsigned long data_len;
+ unsigned long result;
+ int error;
+};
+
+int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
+ unsigned long ioctl_param);
+#endif
diff --git a/security/tlk_driver/ote_types.h b/security/tlk_driver/ote_types.h
new file mode 100644
index 000000000000..ef82d4ffec9d
--- /dev/null
+++ b/security/tlk_driver/ote_types.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OTE_TYPES_H__
+#define __OTE_TYPES_H__
+
+/*
+ * Return Codes
+ */
+enum {
+ /* Success */
+ OTE_SUCCESS = 0x00000000,
+ OTE_ERROR_NO_ERROR = OTE_SUCCESS,
+ /* Non-specific cause */
+ OTE_ERROR_GENERIC = 0xFFFF0000,
+ /* Access priviledge not sufficient */
+ OTE_ERROR_ACCESS_DENIED = 0xFFFF0001,
+ /* The operation was cancelled */
+ OTE_ERROR_CANCEL = 0xFFFF0002,
+ /* Concurrent accesses conflict */
+ OTE_ERROR_ACCESS_CONFLICT = 0xFFFF0003,
+ /* Too much data for req was passed */
+ OTE_ERROR_EXCESS_DATA = 0xFFFF0004,
+ /* Input data was of invalid format */
+ OTE_ERROR_BAD_FORMAT = 0xFFFF0005,
+ /* Input parameters were invalid */
+ OTE_ERROR_BAD_PARAMETERS = 0xFFFF0006,
+ /* Oper invalid in current state */
+ OTE_ERROR_BAD_STATE = 0xFFFF0007,
+ /* The req data item not found */
+ OTE_ERROR_ITEM_NOT_FOUND = 0xFFFF0008,
+ /* The req oper not implemented */
+ OTE_ERROR_NOT_IMPLEMENTED = 0xFFFF0009,
+ /* The req oper not supported */
+ OTE_ERROR_NOT_SUPPORTED = 0xFFFF000A,
+ /* Expected data was missing */
+ OTE_ERROR_NO_DATA = 0xFFFF000B,
+ /* System ran out of resources */
+ OTE_ERROR_OUT_OF_MEMORY = 0xFFFF000C,
+ /* The system is busy */
+ OTE_ERROR_BUSY = 0xFFFF000D,
+ /* Communication failed */
+ OTE_ERROR_COMMUNICATION = 0xFFFF000E,
+ /* A security fault was detected */
+ OTE_ERROR_SECURITY = 0xFFFF000F,
+ /* The supplied buffer is too short */
+ OTE_ERROR_SHORT_BUFFER = 0xFFFF0010,
+};
+
+/*
+ * Return Code origins
+ */
+enum {
+ /* Originated from OTE Client API */
+ OTE_ERROR_ORIGIN_API = 1,
+ /* Originated from Underlying Communication Stack */
+ OTE_ERROR_ORIGIN_COMMS = 2,
+ /* Originated from Common OTE Code */
+ OTE_ERROR_ORIGIN_KERNEL = 3,
+ /* Originated from Trusted APP Code */
+ OTE_ERROR_ORIGIN_TRUSTED_APP = 4,
+};
+
+#endif