diff options
author | Martin Hovang <martin.xm.hovang@stericsson.com> | 2011-05-09 11:57:00 +0200 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:04:35 +0200 |
commit | 845dda7f67651a93e0b8d09f39f17c332c22dc63 (patch) | |
tree | 986d1641afa1b8efd4d17dc6bf6fcc9c64008cd6 /drivers/tee/tee_driver.c | |
parent | ace22919ce9616453b97737e55825fb5ae274136 (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>
Diffstat (limited to 'drivers/tee/tee_driver.c')
-rw-r--r-- | drivers/tee/tee_driver.c | 195 |
1 files changed, 177 insertions, 18 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; } |