summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorVandana Salve <vsalve@nvidia.com>2012-12-10 15:29:06 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:07:13 -0700
commitbb97fa3fcba059275a330adee67e3cb0dd72874f (patch)
treeaa9d7e4a17a81f996384649f05a04cd634360685 /security
parenta467c2704988f3f47d2b70b3d2b8d498559187ab (diff)
security: nv_tee_driver: kernel driver for tlk
Added basic driver support, ioctl interface Added support to lock the temporary and the shared memory buffers Added command parameter descriptor free and used lists Added shmem descriptor to keep track of pinned buffer Added support to unpin temp buffers Change-Id: I048c72bcf98ce0e75264144e66a1f8759b0ba0fe Reviewed-on: http://git-master/r/169837 Reviewed-on: http://git-master/r/190658 Signed-off-by: Vandana Salve <vsalve@nvidia.com> Reviewed-on: http://git-master/r/212074 Reviewed-by: Varun Wadekar <vwadekar@nvidia.com> Tested-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig1
-rw-r--r--security/Makefile2
-rw-r--r--security/nv_tee_driver/Kconfig8
-rw-r--r--security/nv_tee_driver/Makefile27
-rw-r--r--security/nv_tee_driver/tee_client_api.h91
-rw-r--r--security/nv_tee_driver/tee_comms.c360
-rw-r--r--security/nv_tee_driver/tee_device.c467
-rw-r--r--security/nv_tee_driver/tee_irq.S21
-rw-r--r--security/nv_tee_driver/tee_protocol.h216
-rw-r--r--security/nv_tee_driver/tee_types.h109
10 files changed, 1302 insertions, 0 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 7eaaed2293e8..48c38202d998 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -122,6 +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/yama/Kconfig
source security/integrity/Kconfig
diff --git a/security/Makefile b/security/Makefile
index 3312cc35a204..219dc9e71e9c 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -9,6 +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
# always enable default capabilities
obj-y += commoncap.o
@@ -26,6 +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
# Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity
diff --git a/security/nv_tee_driver/Kconfig b/security/nv_tee_driver/Kconfig
new file mode 100644
index 000000000000..ad74e591062b
--- /dev/null
+++ b/security/nv_tee_driver/Kconfig
@@ -0,0 +1,8 @@
+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/Makefile b/security/nv_tee_driver/Makefile
new file mode 100644
index 000000000000..96761c6bd50a
--- /dev/null
+++ b/security/nv_tee_driver/Makefile
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+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)
+
+nv_tee_driver-objs += tee_device.o
+nv_tee_driver-objs += tee_comms.o
+nv_tee_driver-objs += tee_irq.o
+
+obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += nv_tee_driver.o
diff --git a/security/nv_tee_driver/tee_client_api.h b/security/nv_tee_driver/tee_client_api.h
new file mode 100644
index 000000000000..d7b00e1f4516
--- /dev/null
+++ b/security/nv_tee_driver/tee_client_api.h
@@ -0,0 +1,91 @@
+/*
+ * 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];
+};
+
+#endif
diff --git a/security/nv_tee_driver/tee_comms.c b/security/nv_tee_driver/tee_comms.c
new file mode 100644
index 000000000000..f9a5f6e4d56d
--- /dev/null
+++ b/security/nv_tee_driver/tee_comms.c
@@ -0,0 +1,360 @@
+/*
+ * 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);
+
+static int tee_pin_user_pages(void *buffer, size_t size,
+ unsigned long *pages_ptr)
+{
+ int ret = 0, i;
+ unsigned int nr_pages;
+ struct page **pages = NULL;
+
+ nr_pages = (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 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);
+ }
+ }
+}
+
+/*
+ * Do an SMC call
+ */
+static void do_smc(union smc_args_t *smc_args, void *data)
+{
+ unsigned int *args = smc_args->smc;
+
+#ifdef CONFIG_SMP
+ long ret;
+ cpumask_t saved_cpu_mask;
+ cpumask_t local_cpu_mask = CPU_MASK_NONE;
+
+ cpu_set(0, local_cpu_mask);
+ sched_getaffinity(0, &saved_cpu_mask);
+ ret = sched_setaffinity(0, &local_cpu_mask);
+ if (ret != 0)
+ pr_err("sched_setaffinity #1 -> 0x%lX", ret);
+#endif
+
+ if (verbose_smc) {
+ pr_info("SMC call:\n");
+ pr_info(" %08x %08x\n", args[0], args[1]);
+ pr_info(" %08x %08x\n", args[2], args[3]);
+ pr_info(" %08x %08x\n", args[4], args[5]);
+ pr_info(" %08x %08x\n", args[6], args[7]);
+ }
+
+ asm volatile (
+ "stmdb sp!, {r4-r12}\n"
+ "mov r12, %2\n"
+ "ldmia r12, {r0-r7}\n"
+#ifdef REQUIRES_SEC
+ ".arch_extension sec\n"
+#endif
+ "smc #0\n"
+ "ldmia sp!, {r4-r12}\n"
+ "mov r2, %0\n"
+ "str r0, [r2]\n"
+ "mov r2, %1\n"
+ "cmp r2, #0\n"
+ "strne r1, [r2]\n"
+ : : "r" (&smc_args->answer.result), "r" (data), "r" (args)
+ : "r0", "r1", "r2", "r3"
+ );
+
+ if (verbose_smc) {
+ pr_info("SMC result:\n");
+ pr_info(" %08x %08x\n", args[0], args[1]);
+ pr_info(" %08x %08x\n", args[2], args[3]);
+ pr_info(" %08x %08x\n", args[4], args[5]);
+ pr_info(" %08x %08x\n", args[6], args[7]);
+ }
+
+#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(union smc_args_t *smc_buf)
+{
+ smc_buf->request.type = TMK_SMC_GET_MORE;
+ /* rest of smc_buf ignored */
+ do_smc(smc_buf, NULL);
+}
+
+/*
+ * Handle an answer from the secure side.
+ * This should unblock the waiting client (according to session_id number)
+ * and give it back results from smc_buf->answer union field.
+ */
+static void interpret_single_answer(union smc_args_t *smc_buf)
+{
+ pr_info("UNBLOCK client of session %d\n", smc_buf->answer.session_id);
+ pr_info(" result=%08x origin=%08x\n",
+ smc_buf->answer.result, smc_buf->answer.return_origin);
+}
+
+/*
+ * Fetch all pending answers from the secure side.
+ */
+static void interpret_answers(union smc_args_t *smc_buf)
+{
+ /*
+ * Future improvement would be to signal the number
+ * of pending answers from secure side
+ */
+ while (smc_buf->answer.type == TMK_SMC_ANSWER) {
+ interpret_single_answer(smc_buf);
+ get_more_answers(smc_buf);
+ }
+
+ if (smc_buf->answer.type != TMK_SMC_NO_ANSWER)
+ pr_info("Protocol error: expected NO_ANSWER\n");
+}
+
+static void tee_setup_smc_buf(union smc_args_t *smc_buf,
+ uint32_t type, uint32_t session_id,
+ uint32_t command_id, phys_addr_t phy_cmd_page)
+{
+ smc_buf->request.type = type;
+ smc_buf->request.session_id = session_id;
+ smc_buf->request.command_id = command_id;
+ smc_buf->request.cmd_param = phy_cmd_page;
+}
+
+
+/*
+ * Open session SMC (TEEC_OpenSession)
+ */
+int tee_open_session(struct tee_opensession *cmd,
+ phys_addr_t phy_cmd_page,
+ struct tee_answer *answer)
+{
+ union smc_args_t smc_buf;
+ unsigned int id;
+
+ tee_setup_smc_buf(&smc_buf, TMK_SMC_OPEN_SESSION, cmd->login_types,
+ cmd->login_data, phy_cmd_page);
+
+ do_smc(&smc_buf, &id);
+ if (smc_buf.answer.result) {
+ pr_err("Error opening session: %08x %08x\n",
+ smc_buf.answer.result,
+ smc_buf.answer.return_origin);
+ return -1;
+ }
+
+ answer->session_id = id;
+ return 0;
+}
+
+/*
+ * Close session SMC (TEEC_CloseSession)
+ */
+int tee_close_session(uint32_t session_id)
+{
+ union smc_args_t smc_buf;
+
+ tee_setup_smc_buf(&smc_buf, TMK_SMC_CLOSE_SESSION, session_id,
+ 0, 0);
+ do_smc(&smc_buf, NULL);
+ if (smc_buf.answer.result) {
+ pr_info("Error closing session: %08x\n", smc_buf.answer.result);
+ return -1;
+ }
+
+ return 0;
+}
+
+int tee_pin_mem_buffers(void *buffer, size_t size,
+ struct nv_tee_context *context)
+{
+
+ unsigned long pages = NULL;
+ 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 = -EFAULT;
+ 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 = -EFAULT;
+ goto error;
+ }
+
+ return 0;
+error:
+ return ret;
+}
+
+/*
+ * Register Shared Memory SMC (TEEC_RegisterSharedMemory)
+ */
+int tee_register_memory(struct tee_sharedmem *cmd, phys_addr_t phy_cmd_page,
+ struct tee_answer *answer, struct nv_tee_context *context)
+{
+ int ret = 0;
+ union smc_args_t smc_buf;
+
+ ret = tee_pin_mem_buffers(cmd->memref.buffer, cmd->memref.size,
+ context);
+ if (ret < 0) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ tee_setup_smc_buf(&smc_buf, TMK_SMC_REG_SHARED_MEM, cmd->session_id,
+ 0, phy_cmd_page);
+
+ do_smc(&smc_buf, NULL);
+
+ return 0;
+error:
+ return ret;
+}
+
+/*
+ * 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");
+}
+
+/*
+ * Invoke Command SMC (TEEC_InvokeCommand)
+ */
+
+int tee_invoke_command(struct tee_invokecmd *cmd, phys_addr_t phy_cmd_page,
+ struct tee_answer *answer)
+{
+ union smc_args_t smc_buf;
+
+ pr_info("tee_invoke_command: session_id (%d) command_id(%d)\n",
+ cmd->session_id, cmd->command_id);
+
+ tee_setup_smc_buf(&smc_buf, TMK_SMC_INVOKE_CMD, cmd->session_id,
+ cmd->command_id, phy_cmd_page);
+
+ do_smc(&smc_buf, NULL);
+
+ if (smc_buf.answer.result) {
+ pr_err("Error opening session: %08x %08x\n",
+ smc_buf.answer.result,
+ smc_buf.answer.return_origin);
+ return -1;
+ }
+ return 0;
+}
+
+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
new file mode 100644
index 000000000000..8270b3290076
--- /dev/null
+++ b/security/nv_tee_driver/tee_device.c
@@ -0,0 +1,467 @@
+/*
+ * 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 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;
+
+static int tee_device_setup_operation_params(struct tee_cmd_param *param,
+ struct TEEC_Operation *operation)
+{
+ uint32_t i, type;
+ int ret = TEEC_SUCCESS;
+
+ param->param_types = operation->paramTypes;
+ for (i = 0; i < 4; 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;
+#if 0
+ /* XXX support for these requires some work */
+ case TEEC_PARAM_TYPE_MEMREF_WHOLE:
+ case TEEC_PARAM_TYPE_MEMREF_PARTIAL_INPUT:
+ case TEEC_PARAM_TYPE_MEMREF_PARTIAL_OUTPUT:
+ case TEEC_PARAM_TYPE_MEMREF_PARTIAL_INOUT:
+ break;
+#endif
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
+ }
+ return 0;
+}
+
+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 < 4; 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("Pin buffer failed err (%d)\n", ret);
+ break;
+ }
+ break;
+ default:
+ pr_err("Pin buffer TEEC_ERROR_BAD_PARAMETERS\n");
+ ret = TEEC_ERROR_BAD_PARAMETERS;
+ }
+ }
+ return ret;
+}
+
+static int tee_unpin_temp_buffers(struct TEEC_Operation *oper,
+ struct nv_tee_context *context)
+{
+ uint32_t i, type;
+ int ret = TEEC_SUCCESS;
+
+ for (i = 0; i < 4; 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_pin_mem_buffers: TEEC_ERROR_BAD_PARAMETERS\n");
+ ret = TEEC_ERROR_BAD_PARAMETERS;
+ }
+ }
+ 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 void tee_print_opensession_cmd(struct tee_opensession *opensession)
+{
+ int i;
+ pr_info("UUID time low (%x)\n", opensession->dest_uuid.time_low);
+ pr_info("UUID time low (%x)\n", opensession->dest_uuid.time_mid);
+ pr_info("UUID time_hi_and_version (%x)\n",
+ opensession->dest_uuid.time_hi_and_version);
+ pr_info("login type (%d)\n", opensession->login_types);
+ if (opensession->login_data)
+ pr_info("login data (%d)\n", opensession->login_data);
+ for (i = 0; i < 4; i++)
+ pr_info("Param#(%d) : param_type (%d)\n", i,
+ TEEC_PARAM_TYPE_GET(
+ (opensession->operation.paramTypes),
+ i));
+}
+
+static int tee_device_open(struct inode *inode, struct file *file)
+{
+ struct nv_tee_context *context;
+ int ret = 0;
+
+ pr_info("tee_device_open\n");
+ 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)
+{
+ pr_info("tee_device_release\n");
+ kfree(file->private_data);
+ file->private_data = NULL;
+ return 0;
+}
+
+static long tee_device_ioctl(struct file *file, unsigned int ioctl_num,
+ unsigned long ioctl_param)
+{
+ int err = TEEC_SUCCESS;
+ union tee_cmd command;
+ void *ptr_user_answer = NULL;
+ struct tee_answer answer;
+ struct tee_cmd_param *param;
+ 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(&command, (void __user *)ioctl_param,
+ sizeof(union tee_cmd))) {
+ pr_err("Failed to copy command request\n");
+ goto error;
+ }
+
+ memset(&answer, 0, sizeof(struct tee_answer));
+ switch (ioctl_num) {
+ case TEE_IOCTL_OPEN_CLIENT_SESSION:
+ ptr_user_answer = (void *)command.opensession.answer;
+
+ cmd_desc = tee_get_free_cmd_desc(nv_dev);
+ if (cmd_desc) {
+ param = (struct tee_cmd_param *)
+ cmd_desc->param_addr;
+
+ err = tee_device_setup_operation_params(param,
+ &command.opensession.operation);
+ if (err != TEEC_SUCCESS) {
+ pr_err("setup operation params failed\n");
+ goto error;
+ }
+
+ err = tee_setup_temp_buffers(
+ &command.opensession.operation, context);
+ if (err != TEEC_SUCCESS) {
+ pr_err("setup temp buf failed err (%d)\n", err);
+ goto error;
+ }
+
+ memcpy(&param->dest_uuid,
+ &command.opensession.dest_uuid,
+ sizeof(struct TEEC_UUID));
+
+ err = tee_open_session(&command.opensession,
+ virt_to_phys((void *)cmd_desc->param_addr),
+ &answer);
+ if (err)
+ pr_err("open session failed with err (%d)\n",
+ err);
+ err = tee_unpin_temp_buffers(
+ &command.opensession.operation, context);
+ } else {
+ pr_err("failed to get cmd_desc\n");
+ goto error;
+ }
+ break;
+
+ case TEE_IOCTL_CLOSE_CLIENT_SESSION:
+ ptr_user_answer = (void *)command.closesession.answer;
+ err = tee_close_session(command.closesession.session_id);
+ if (err)
+ pr_err("close session failed with error %d\n", err);
+ break;
+
+ case TEE_IOCTL_REGISTER_MEMORY:
+ ptr_user_answer = (void *)command.sharedmem.answer;
+ cmd_desc = tee_get_free_cmd_desc(nv_dev);
+ if (cmd_desc) {
+ param = (struct tee_cmd_param *)
+ cmd_desc->param_addr;
+ param->param_types = command.sharedmem.memref.flags;
+ param->params[0].memref.buffer =
+ command.sharedmem.memref.buffer;
+ param->params[0].memref.size =
+ command.sharedmem.memref.size;
+ }
+
+ err = tee_register_memory(&(command.sharedmem),
+ virt_to_phys((void *)cmd_desc->param_addr),
+ &answer,
+ context);
+ if (err)
+ pr_err("memory registor failed with error %d\n", err);
+ break;
+
+ case TEE_IOCTL_RELEASE_SHARED_MEM:
+ tee_unregister_memory(command.release_shared_mem.buffer,
+ context);
+ break;
+
+ case TEE_IOCTL_INVOKE_COMMAND:
+ ptr_user_answer = (void *)command.invokecmd.answer;
+ cmd_desc = tee_get_free_cmd_desc(nv_dev);
+ if (cmd_desc) {
+ param = (struct tee_cmd_param *)
+ cmd_desc->param_addr;
+ err = tee_device_setup_operation_params(param,
+ &command.invokecmd.operation);
+ if (err != TEEC_SUCCESS) {
+ pr_err("tee_device_setup_operation_params failed\n");
+ goto error;
+ }
+
+ err = tee_setup_temp_buffers(
+ &command.invokecmd.operation, context);
+ if (err != TEEC_SUCCESS) {
+ pr_err("setup temp buffers failed err (%d)\n",
+ err);
+ goto error;
+ }
+
+ err = tee_invoke_command(&(command.invokecmd),
+ virt_to_phys((void *)cmd_desc->param_addr),
+ &answer);
+ if (err) {
+ pr_err("Invoke cmd id (%u) failed err (%d)\n",
+ command.invokecmd.command_id, err);
+ }
+ err = tee_unpin_temp_buffers(
+ &command.invokecmd.operation, context);
+ } else {
+ pr_err("failed to get cmd_desc\n");
+ }
+ 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 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 nv_cmd_param_desc) * 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;
+
+}
+
+/*
+ * 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_irq.S b/security/nv_tee_driver/tee_irq.S
new file mode 100644
index 000000000000..4e913cb24c03
--- /dev/null
+++ b/security/nv_tee_driver/tee_irq.S
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ENTRY(nv_tee_irq_handler)
+ movw r0, #0x1FF1
+ movt r0, #0xFFFF
+ smc #0
+ENDPROC(nv_tee_irq_handler)
diff --git a/security/nv_tee_driver/tee_protocol.h b/security/nv_tee_driver/tee_protocol.h
new file mode 100644
index 000000000000..8983cad7624d
--- /dev/null
+++ b/security/nv_tee_driver/tee_protocol.h
@@ -0,0 +1,216 @@
+/*
+ * 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_MIN_NR _IOC_NR(TEE_IOCTL_OPEN_CLIENT_SESSION)
+#define TEE_IOCTL_MAX_NR _IOC_NR(TEE_IOCTL_REQ_CANCELLATION)
+
+#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;
+};
+
+struct tee_request {
+ uint32_t type;
+ uint32_t session_id;
+ uint32_t command_id;
+ phys_addr_t cmd_param;
+};
+
+struct tee_answer {
+ uint32_t type;
+ uint32_t result;
+ uint32_t return_origin;
+ uint32_t session_id;
+ union TEEC_Param params[4];
+};
+
+/*
+ * 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];
+};
+
+/*
+ * SMC protocol union
+ */
+union smc_args_t {
+ struct tee_request request;
+ struct tee_answer answer;
+ unsigned int smc[8];
+};
+
+int tee_open_session(struct tee_opensession *cmd,
+ phys_addr_t phy_cmd_page,
+ struct tee_answer *answer);
+
+int tee_close_session(uint32_t session_id);
+
+int tee_register_memory(struct tee_sharedmem *cmd,
+ phys_addr_t phy_cmd_page,
+ struct tee_answer *answer,
+ struct nv_tee_context *context);
+
+void tee_unregister_memory(void *buffer,
+ struct nv_tee_context *context);
+
+int tee_invoke_command(struct tee_invokecmd *cmd,
+ phys_addr_t phy_cmd_page,
+ struct tee_answer *answer);
+
+int tee_pin_mem_buffers(void *buffer, size_t size,
+ struct nv_tee_context *context);
+#endif
diff --git a/security/nv_tee_driver/tee_types.h b/security/nv_tee_driver/tee_types.h
new file mode 100644
index 000000000000..c1233f4eb47a
--- /dev/null
+++ b/security/nv_tee_driver/tee_types.h
@@ -0,0 +1,109 @@
+/*
+ * 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