summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hovang <martin.xm.hovang@stericsson.com>2011-05-09 11:57:00 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:04:35 +0200
commit845dda7f67651a93e0b8d09f39f17c332c22dc63 (patch)
tree986d1641afa1b8efd4d17dc6bf6fcc9c64008cd6
parentace22919ce9616453b97737e55825fb5ae274136 (diff)
TEE: Added TEE kernel interface
ST-Ericsson ID: 337171 ST Ericsson FOSS-OUT ID: Trivial ST Ericsson Linux next: Not tested Change-Id: I4c87bd550547a1fd90f1fef8c3c553246940b31e Signed-off-by: Martin Hovang <martin.xm.hovang@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22666 Reviewed-by: QATEST Reviewed-by: Joakim BECH <joakim.xx.bech@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r--drivers/tee/tee_driver.c195
-rw-r--r--include/linux/tee.h135
2 files changed, 311 insertions, 19 deletions
diff --git a/drivers/tee/tee_driver.c b/drivers/tee/tee_driver.c
index 551c92cc054..73c62871ddc 100644
--- a/drivers/tee/tee_driver.c
+++ b/drivers/tee/tee_driver.c
@@ -21,8 +21,7 @@
#define TEED_STATE_OPEN_DEV 0
#define TEED_STATE_OPEN_SESSION 1
-#define TEEC_MEM_INPUT 0x00000001
-#define TEEC_MEM_OUTPUT 0x00000002
+static struct mutex sync;
static int tee_open(struct inode *inode, struct file *file);
static int tee_release(struct inode *inode, struct file *file);
@@ -281,13 +280,6 @@ static int tee_open(struct inode *inode, struct file *filp)
reset_session(ts);
- ts->sync = kmalloc(sizeof(struct mutex), GFP_KERNEL);
-
- if (!ts->sync)
- return -ENOMEM;
-
- mutex_init(ts->sync);
-
return 0;
}
@@ -311,9 +303,6 @@ static int tee_release(struct inode *inode, struct file *filp)
kfree(ts->op);
ts->op = NULL;
- kfree(ts->sync);
- ts->sync = NULL;
-
kfree(ts->ta);
ts->ta = NULL;
@@ -342,18 +331,18 @@ static int tee_read(struct file *filp, char __user *buffer,
ts = (struct tee_session *) (filp->private_data);
- if (ts == NULL || ts->sync == NULL) {
+ if (ts == NULL) {
pr_err("[%s] error, private_data not "
"initialized\n", __func__);
return -EINVAL;
}
- mutex_lock(ts->sync);
+ mutex_lock(&sync);
buf.err = ts->err;
buf.origin = ts->origin;
- mutex_unlock(ts->sync);
+ mutex_unlock(&sync);
if (copy_to_user(buffer, &buf, length)) {
pr_err("[%s] error, copy_to_user failed!\n",
@@ -388,13 +377,13 @@ static int tee_write(struct file *filp, const char __user *buffer,
ts = (struct tee_session *) (filp->private_data);
- if (ts == NULL || ts->sync == NULL) {
+ if (ts == NULL) {
pr_err("[%s] error, private_data not "
"initialized\n", __func__);
return -EINVAL;
}
- mutex_lock(ts->sync);
+ mutex_lock(&sync);
switch (ts->state) {
case TEED_STATE_OPEN_DEV:
@@ -439,11 +428,179 @@ static int tee_write(struct file *filp, const char __user *buffer,
else
ret = -EINVAL;
- mutex_unlock(ts->sync);
+ mutex_unlock(&sync);
return ret;
}
+int teec_initialize_context(const char *name, struct tee_context *context)
+{
+ return TEED_SUCCESS;
+}
+EXPORT_SYMBOL(teec_initialize_context);
+
+int teec_finalize_context(struct tee_context *context)
+{
+ return TEED_SUCCESS;
+}
+EXPORT_SYMBOL(teec_finalize_context);
+
+int teec_open_session(struct tee_context *context,
+ struct tee_session *session,
+ const struct tee_uuid *destination,
+ unsigned int connection_method,
+ void *connection_data, struct tee_operation *operation,
+ unsigned int *error_origin)
+{
+ int res = TEED_SUCCESS;
+
+ if (session == NULL || destination == NULL) {
+ pr_err("[%s] session or destination == NULL\n", __func__);
+ if (error_origin != NULL)
+ *error_origin = TEED_ORIGIN_DRIVER;
+ res = TEED_ERROR_BAD_PARAMETERS;
+ goto exit;
+ }
+
+ reset_session(session);
+
+ /*
+ * Open a session towards an application already loaded inside
+ * the TEE
+ */
+ session->uuid = kmalloc(sizeof(struct tee_uuid), GFP_KERNEL);
+
+ if (session->uuid == NULL) {
+ pr_err("[%s] error, out of memory (uuid)\n",
+ __func__);
+ if (error_origin != NULL)
+ *error_origin = TEED_ORIGIN_DRIVER;
+ res = TEED_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ memcpy(session->uuid, destination, sizeof(struct tee_uuid));
+
+ session->ta = NULL;
+ session->id = 0;
+
+exit:
+ return res;
+}
+EXPORT_SYMBOL(teec_open_session);
+
+int teec_close_session(struct tee_session *session)
+{
+ int res = TEED_SUCCESS;
+
+ mutex_lock(&sync);
+
+ if (session == NULL) {
+ pr_err("[%s] error, session == NULL\n", __func__);
+ res = TEED_ERROR_BAD_PARAMETERS;
+ goto exit;
+ }
+
+ if (call_sec_world(session, TEED_CLOSE_SESSION)) {
+ pr_err("[%s] error, call_sec_world failed\n", __func__);
+ res = TEED_ERROR_GENERIC;
+ goto exit;
+ }
+
+exit:
+ if (session != NULL) {
+ kfree(session->uuid);
+ session->uuid = NULL;
+ }
+
+ mutex_unlock(&sync);
+ return res;
+}
+EXPORT_SYMBOL(teec_close_session);
+
+int teec_invoke_command(
+ struct tee_session *session, unsigned int command_id,
+ struct tee_operation *operation,
+ unsigned int *error_origin)
+{
+ int res = TEED_SUCCESS;
+ int i;
+
+ mutex_lock(&sync);
+
+ if (session == NULL || operation == NULL || error_origin == NULL) {
+ pr_err("[%s] error, input parameters == NULL\n", __func__);
+ if (error_origin != NULL)
+ *error_origin = TEED_ORIGIN_DRIVER;
+ res = TEED_ERROR_BAD_PARAMETERS;
+ goto exit;
+ }
+
+ for (i = 0; i < 4; ++i) {
+ /* We only want to translate memrefs in use. */
+ if (operation->flags & (1 << i)) {
+ operation->shm[i].buffer =
+ (void *)virt_to_phys(
+ operation->shm[i].buffer);
+ }
+ }
+ session->op = operation;
+ session->cmd = command_id;
+
+ /*
+ * Call secure world
+ */
+ if (call_sec_world(session, TEED_INVOKE)) {
+ pr_err("[%s] error, call_sec_world failed\n", __func__);
+ if (error_origin != NULL)
+ *error_origin = TEED_ORIGIN_DRIVER;
+ res = TEED_ERROR_GENERIC;
+ }
+ if (session->err != TEED_SUCCESS) {
+ pr_err("[%s] error, call_sec_world failed\n", __func__);
+ if (error_origin != NULL)
+ *error_origin = session->origin;
+ res = session->err;
+ }
+
+ memrefs_phys_to_virt(session);
+ session->op = NULL;
+
+exit:
+ mutex_unlock(&sync);
+ return res;
+}
+EXPORT_SYMBOL(teec_invoke_command);
+
+int teec_allocate_shared_memory(struct tee_context *context,
+ struct tee_sharedmemory *shared_memory)
+{
+ int res = TEED_SUCCESS;
+
+ if (shared_memory == NULL) {
+ res = TEED_ERROR_BAD_PARAMETERS;
+ goto exit;
+ }
+
+ shared_memory->buffer = kmalloc(shared_memory->size,
+ GFP_KERNEL);
+
+ if (shared_memory->buffer == NULL) {
+ res = TEED_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+exit:
+ return res;
+}
+EXPORT_SYMBOL(teec_allocate_shared_memory);
+
+void teec_release_shared_memory(struct tee_sharedmemory *shared_memory)
+{
+ kfree(shared_memory->buffer);
+}
+EXPORT_SYMBOL(teec_release_shared_memory);
+
static const struct file_operations tee_fops = {
.owner = THIS_MODULE,
.read = tee_read,
@@ -469,6 +626,8 @@ static int __init tee_init(void)
"TEE\n", __func__, err);
}
+ mutex_init(&sync);
+
return err;
}
diff --git a/include/linux/tee.h b/include/linux/tee.h
index 0cdec2d254a..4928e4dca1f 100644
--- a/include/linux/tee.h
+++ b/include/linux/tee.h
@@ -3,7 +3,7 @@
*
* Copyright (C) ST-Ericsson SA 2010
* Author: Shujuan Chen <shujuan.chen@stericsson.com>
- * Author: Martin Hovang <martin.xm.hovang@stericsson.com
+ * Author: Martin Hovang <martin.xm.hovang@stericsson.com>
* Author: Joakim Bech <joakim.xx.bech@stericsson.com>
* License terms: GNU General Public License (GPL) version 2
*/
@@ -45,6 +45,37 @@
#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4
+/*
+ * Flag constants indicating which of the memory references in an open session
+ * or invoke command operation payload (TEEC_Operation) that are used.
+ */
+#define TEEC_MEMREF_0_USED 0x00000001
+#define TEEC_MEMREF_1_USED 0x00000002
+#define TEEC_MEMREF_2_USED 0x00000004
+#define TEEC_MEMREF_3_USED 0x00000008
+
+/*
+ * Flag constants indicating the data transfer direction of memory in
+ * TEEC_SharedMemory and TEEC_MemoryReference. TEEC_MEM_INPUT signifies data
+ * transfer direction from the client application to the TEE. TEEC_MEM_OUTPUT
+ * signifies data transfer direction from the TEE to the client application.
+ */
+#define TEEC_MEM_INPUT 0x00000001
+#define TEEC_MEM_OUTPUT 0x00000002
+
+/*
+ * Session login methods, for use in TEEC_OpenSession() as parameter
+ * connectionMethod. Type is t_uint32.
+ *
+ * TEEC_LOGIN_PUBLIC No login data is provided.
+ */
+#define TEEC_LOGIN_PUBLIC 0x0
+
+/*
+ * Exposed functions (command_id) in the static TA
+ */
+#define TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER 11
+
/**
* struct tee_uuid - Structure that represent an uuid.
* @timeLow: The low field of the time stamp.
@@ -85,6 +116,8 @@ struct tee_operation {
uint32_t flags;
};
+struct tee_context {};
+
/**
* struct tee_session - The session of an open tee device.
* @state: The current state in the linux kernel.
@@ -140,4 +173,104 @@ struct tee_read {
*/
int call_sec_world(struct tee_session *ts, int sec_cmd);
+
+/**
+ * teec_initialize_context() - Initializes a context holding connection
+ * information on the specific TEE.
+ * @param name: A zero-terminated string identifying the TEE to connect to.
+ * If name is set to NULL, the default TEE is connected to.
+ * NULL is the only supported value in this version of the
+ * API implementation.
+ * @param context: The context structure which is to be initialized.
+ *
+ * Initializes a context holding connection information between the calling
+ * client application and the TEE designated by the name string.
+ */
+int teec_initialize_context(const char *name, struct tee_context *context);
+
+/**
+ * teec_finalize_context() - Destroys a context holding connection information
+ * on the specific TEE.
+ * @param context: The context to be destroyed.
+ *
+ * This function destroys an initialized TEE context, closing the connection
+ * between the client application and the TEE. This function must only be
+ * called when all sessions related to this TEE context have been closed and
+ * all shared memory blocks have been released.
+ */
+int teec_finalize_context(struct tee_context *context);
+
+/**
+ * teec_open_session() - Opens a new session with the specified trusted
+ * application.
+ * @param context: The initialized TEE context structure in which scope to
+ * open the session.
+ * @param session: The session to initialize.
+ * @param destination: A structure identifying the trusted application with
+ * which to open a session. If this is set to NULL the
+ * operation TEEC_MEMREF_0 is expected to contain the blob
+ * which holds the Trusted Application.
+ * @param connection_method: The connection method to use.
+ * @param connection_data: Any data necessary to connect with the chosen
+ * connection method. Not supported should be set to
+ * NULL.
+ * @param operation: An operation structure to use in the session. May be
+ * set to NULL to signify no operation structure needed.
+ * If destination is set to NULL, TEEC_MEMREF_0 is
+ * expected to hold the TA binary as described above.
+ * @param error_origin: A parameter which will hold the error origin if this
+ * function returns any value other than TEEC_SUCCESS.
+ *
+ * Opens a new session with the specified trusted application. Only
+ * connectionMethod == TEEC_LOGIN_PUBLIC is supported. connectionData and
+ * operation shall be set to NULL.
+ */
+int teec_open_session(struct tee_context *context, struct tee_session *session,
+ const struct tee_uuid *destination,
+ unsigned int connection_method,
+ void *connection_data, struct tee_operation *operation,
+ unsigned int *error_origin);
+
+/**
+ * teec_close_session() - Closes the session which has been opened with the
+ * specific trusted application.
+ * @param session: The opened session to close.
+ *
+ * Closes the session which has been opened with the specific trusted
+ * application.
+ */
+int teec_close_session(struct tee_session *session);
+
+/**
+ * teec_invoke_command() - Executes a command in the specified trusted
+ * application.
+ * @param destination: A structure identifying the trusted application.
+ * @param command_id: Identifier of the command in the trusted application to
+ * invoke.
+ * @param operation: An operation structure to use in the invoke command. May
+ * be set to NULL to signify no operation structure needed.
+ * @param error_origin: A parameter which will hold the error origin if this
+ * function returns any value other than TEEC_SUCCESS.
+ *
+ * Executes a command in the specified trusted application.
+ */
+int teec_invoke_command(struct tee_session *session, unsigned int command_id,
+ struct tee_operation *operation,
+ unsigned int *error_origin);
+
+/**
+ * teec_allocate_shared_memory() - Allocate shared memory for TEE.
+ * @param context: The initialized TEE context structure in which scope to
+ * open the session.
+ * @param shared_memory: Pointer to the allocated shared memory.
+ */
+int teec_allocate_shared_memory(struct tee_context *context,
+ struct tee_sharedmemory *shared_memory);
+
+/**
+ * teec_release_shared_memory() - Free the shared memory.
+ * @param shared_memory: Pointer to the shared memory to be freed.
+ */
+void teec_release_shared_memory(struct tee_sharedmemory *shared_memory);
+
#endif