From 845dda7f67651a93e0b8d09f39f17c332c22dc63 Mon Sep 17 00:00:00 2001 From: Martin Hovang Date: Mon, 9 May 2011 11:57:00 +0200 Subject: 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 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22666 Reviewed-by: QATEST Reviewed-by: Joakim BECH Reviewed-by: Jonas ABERG --- drivers/tee/tee_driver.c | 195 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/tee.h | 135 +++++++++++++++++++++++++++++++- 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 - * Author: Martin Hovang * Author: Joakim Bech * 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 -- cgit v1.2.3