From 04468bc1d72f15e6b8f19014e8c6203038dd6b23 Mon Sep 17 00:00:00 2001 From: Maggie White Date: Fri, 2 Jun 2017 18:10:06 -0700 Subject: [PATCH] msm: gud: Remove gud driver Complete removal of gud mobicore driver. The driver author delivers an updated version of the driver to interested parties directly rendering this version obsolete. Bug: 33842910 CRs-Fixed: 1116560 Change-Id: I40498d3203b1d6ca04f2b5a2e65461851d84d2d4 Acked-by: Tony Hamilton Signed-off-by: Trudy Shearer Signed-off-by: Dennis Cagle Signed-off-by: Maggie White --- drivers/Kconfig | 2 - drivers/Makefile | 3 - drivers/gud/Kconfig | 35 - drivers/gud/Makefile | 6 - drivers/gud/MobiCoreDriver/Makefile | 33 - drivers/gud/MobiCoreDriver/admin.c | 1011 ------------------- drivers/gud/MobiCoreDriver/admin.h | 32 - drivers/gud/MobiCoreDriver/api.c | 419 -------- drivers/gud/MobiCoreDriver/api.h | 46 - drivers/gud/MobiCoreDriver/arm.h | 88 -- drivers/gud/MobiCoreDriver/build_tag.h | 15 - drivers/gud/MobiCoreDriver/client.c | 572 ----------- drivers/gud/MobiCoreDriver/client.h | 99 -- drivers/gud/MobiCoreDriver/clientlib.c | 433 -------- drivers/gud/MobiCoreDriver/clock.c | 161 --- drivers/gud/MobiCoreDriver/clock.h | 53 - drivers/gud/MobiCoreDriver/debug.h | 63 -- drivers/gud/MobiCoreDriver/fastcall.c | 512 ---------- drivers/gud/MobiCoreDriver/fastcall.h | 38 - drivers/gud/MobiCoreDriver/logging.c | 251 ----- drivers/gud/MobiCoreDriver/logging.h | 51 - drivers/gud/MobiCoreDriver/main.c | 750 -------------- drivers/gud/MobiCoreDriver/main.h | 60 -- drivers/gud/MobiCoreDriver/mci/mcifc.h | 144 --- drivers/gud/MobiCoreDriver/mci/mcimcp.h | 508 ---------- drivers/gud/MobiCoreDriver/mci/mcinq.h | 86 -- drivers/gud/MobiCoreDriver/mci/mcloadformat.h | 134 --- drivers/gud/MobiCoreDriver/mcp.c | 1067 -------------------- drivers/gud/MobiCoreDriver/mcp.h | 121 --- drivers/gud/MobiCoreDriver/mmu.c | 450 --------- drivers/gud/MobiCoreDriver/mmu.h | 44 - drivers/gud/MobiCoreDriver/platform.h | 150 --- drivers/gud/MobiCoreDriver/pm.c | 62 -- drivers/gud/MobiCoreDriver/pm.h | 36 - drivers/gud/MobiCoreDriver/public/mc_admin.h | 80 -- drivers/gud/MobiCoreDriver/public/mc_linux.h | 170 ---- drivers/gud/MobiCoreDriver/public/mc_linux_api.h | 28 - .../MobiCoreDriver/public/mobicore_driver_api.h | 450 --------- drivers/gud/MobiCoreDriver/scheduler.c | 231 ----- drivers/gud/MobiCoreDriver/scheduler.h | 25 - drivers/gud/MobiCoreDriver/session.c | 779 -------------- drivers/gud/MobiCoreDriver/session.h | 63 -- drivers/gud/setupDrivers.sh | 19 - 43 files changed, 9380 deletions(-) delete mode 100644 drivers/gud/Kconfig delete mode 100644 drivers/gud/Makefile delete mode 100644 drivers/gud/MobiCoreDriver/Makefile delete mode 100644 drivers/gud/MobiCoreDriver/admin.c delete mode 100644 drivers/gud/MobiCoreDriver/admin.h delete mode 100644 drivers/gud/MobiCoreDriver/api.c delete mode 100644 drivers/gud/MobiCoreDriver/api.h delete mode 100644 drivers/gud/MobiCoreDriver/arm.h delete mode 100644 drivers/gud/MobiCoreDriver/build_tag.h delete mode 100644 drivers/gud/MobiCoreDriver/client.c delete mode 100644 drivers/gud/MobiCoreDriver/client.h delete mode 100644 drivers/gud/MobiCoreDriver/clientlib.c delete mode 100644 drivers/gud/MobiCoreDriver/clock.c delete mode 100644 drivers/gud/MobiCoreDriver/clock.h delete mode 100644 drivers/gud/MobiCoreDriver/debug.h delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.c delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.h delete mode 100644 drivers/gud/MobiCoreDriver/logging.c delete mode 100644 drivers/gud/MobiCoreDriver/logging.h delete mode 100644 drivers/gud/MobiCoreDriver/main.c delete mode 100644 drivers/gud/MobiCoreDriver/main.h delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcifc.h delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcimcp.h delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcinq.h delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcloadformat.h delete mode 100644 drivers/gud/MobiCoreDriver/mcp.c delete mode 100644 drivers/gud/MobiCoreDriver/mcp.h delete mode 100644 drivers/gud/MobiCoreDriver/mmu.c delete mode 100644 drivers/gud/MobiCoreDriver/mmu.h delete mode 100644 drivers/gud/MobiCoreDriver/platform.h delete mode 100644 drivers/gud/MobiCoreDriver/pm.c delete mode 100644 drivers/gud/MobiCoreDriver/pm.h delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_admin.h delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux.h delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux_api.h delete mode 100644 drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.c delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.h delete mode 100644 drivers/gud/MobiCoreDriver/session.c delete mode 100644 drivers/gud/MobiCoreDriver/session.h delete mode 100644 drivers/gud/setupDrivers.sh diff --git a/drivers/Kconfig b/drivers/Kconfig index 0e7c68c62542a..8b796ec00009e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -200,8 +200,6 @@ source "drivers/firmware/Kconfig" source "drivers/bif/Kconfig" -source "drivers/gud/Kconfig" - source "drivers/htc_mnemosyne/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index fb0cd18143ad5..13236262a1857 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -171,9 +171,6 @@ obj-$(CONFIG_BIF) += bif/ obj-$(CONFIG_SENSORS_SSC) += sensors/ -# -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_admin.h" - -#include "mci/mcloadformat.h" - -#include "main.h" -#include "debug.h" -#include "mmu.h" /* For load_check and load_token */ -#include "mcp.h" -#include "client.h" -#include "api.h" -#include "admin.h" - -/* We need 2 devices for admin and user interface*/ -#define MC_DEV_MAX 2 - -static struct admin_ctx { - struct device *dev; - atomic_t daemon_counter; - /* Define a MobiCore device structure for use with dev_debug() etc */ - struct device_driver mc_dev_name; - dev_t mc_dev_admin; - struct cdev mc_admin_cdev; - int (*tee_start_cb)(void); -} g_admin_ctx; - -static struct mc_admin_driver_request { - /* Global */ - struct mutex mutex; /* Protects access to this struct */ - struct mutex states_mutex; /* Protect access to the states */ - enum client_state { - IDLE, - REQUEST_SENT, - BUFFERS_READY, - } client_state; - enum server_state { - NOT_CONNECTED, /* Device not open */ - READY, /* Waiting for requests */ - REQUEST_RECEIVED, /* Got a request, is working */ - RESPONSE_SENT, /* Has sent a response header */ - DATA_SENT, /* Blocked until data is consumed */ - } server_state; - /* Request */ - uint32_t request_id; - struct mc_admin_request request; - struct completion client_complete; - /* Response */ - struct mc_admin_response response; - struct completion server_complete; - void *buffer; /* Reception buffer (pre-allocated) */ - size_t size; /* Size of the reception buffer */ -} g_request; - -static struct tbase_object *tbase_object_alloc(bool is_sp_trustlet, - size_t length) -{ - struct tbase_object *obj; - size_t size = sizeof(*obj) + length; - size_t header_length = 0; - - /* Determine required size */ - if (is_sp_trustlet) { - /* Need space for lengths info and containers */ - header_length = sizeof(struct mc_blob_len_info); - size += header_length + 3 * MAX_SO_CONT_SIZE; - } - - /* Allocate memory */ - obj = vzalloc(size); - if (!obj) - return NULL; - - /* A non-zero header_length indicates that we have a SP trustlet */ - obj->header_length = header_length; - obj->length = length; - return obj; -} - -void tbase_object_free(struct tbase_object *robj) -{ - vfree(robj); -} - -static inline void client_state_change(enum client_state state) -{ - mutex_lock(&g_request.states_mutex); - g_request.client_state = state; - mutex_unlock(&g_request.states_mutex); -} - -static inline bool client_state_is(enum client_state state) -{ - bool is; - - mutex_lock(&g_request.states_mutex); - is = g_request.client_state == state; - mutex_unlock(&g_request.states_mutex); - return is; -} - -static inline void server_state_change(enum server_state state) -{ - mutex_lock(&g_request.states_mutex); - g_request.server_state = state; - mutex_unlock(&g_request.states_mutex); -} - -static inline bool server_state_is(enum server_state state) -{ - bool is; - - mutex_lock(&g_request.states_mutex); - is = g_request.server_state == state; - mutex_unlock(&g_request.states_mutex); - return is; -} - -static void request_cancel(void); - -static int request_send(uint32_t command, const struct mc_uuid_t *uuid, - uint32_t is_gp, uint32_t spid) -{ - struct device *dev = g_admin_ctx.dev; - int counter = 10; - int ret; - - /* Prepare request */ - mutex_lock(&g_request.states_mutex); - /* Wait a little for daemon to connect */ - while ((g_request.server_state == NOT_CONNECTED) && counter--) { - mutex_unlock(&g_request.states_mutex); - ssleep(1); - mutex_lock(&g_request.states_mutex); - } - - BUG_ON(g_request.client_state != IDLE); - if (g_request.server_state != READY) { - mutex_unlock(&g_request.states_mutex); - if (g_request.server_state != NOT_CONNECTED) { - /* TODO: can we recover? */ - dev_err(dev, "%s: invalid daemon state %d\n", __func__, - g_request.server_state); - ret = -EPROTO; - goto end; - } else { - dev_err(dev, "%s: daemon not connected\n", __func__); - ret = -ENOTCONN; - goto end; - } - } - - memset(&g_request.request, 0, sizeof(g_request.request)); - memset(&g_request.response, 0, sizeof(g_request.response)); - g_request.request.request_id = g_request.request_id++; - g_request.request.command = command; - if (uuid) - memcpy(&g_request.request.uuid, uuid, sizeof(*uuid)); - else - memset(&g_request.request.uuid, 0, sizeof(*uuid)); - - g_request.request.is_gp = is_gp; - g_request.request.spid = spid; - g_request.client_state = REQUEST_SENT; - mutex_unlock(&g_request.states_mutex); - - /* Send request */ - complete(&g_request.client_complete); - - /* Wait for header (could be interruptible, but then needs more work) */ - wait_for_completion(&g_request.server_complete); - - /* Server should be waiting with some data for us */ - mutex_lock(&g_request.states_mutex); - switch (g_request.server_state) { - case NOT_CONNECTED: - /* Daemon gone */ - ret = -EPIPE; - break; - case READY: - /* No data to come, likely an error */ - ret = -g_request.response.error_no; - break; - case RESPONSE_SENT: - case DATA_SENT: - /* Normal case, data to come */ - ret = 0; - break; - default: - /* Should not happen as complete means the state changed */ - dev_err(dev, "%s: daemon is in a bad state: %d\n", __func__, - g_request.server_state); - ret = -EPIPE; - break; - } - - mutex_unlock(&g_request.states_mutex); - -end: - if (ret) - request_cancel(); - - return ret; -} - -static int request_receive(void *address, uint32_t size) -{ - /* - * At this point we have received the header and prepared some buffers - * to receive data that we know are coming from the server. - */ - - /* Check server state */ - bool server_ok; - - mutex_lock(&g_request.states_mutex); - server_ok = (g_request.server_state == RESPONSE_SENT) || - (g_request.server_state == DATA_SENT); - mutex_unlock(&g_request.states_mutex); - if (!server_ok) { - /* TODO: can we recover? */ - request_cancel(); - return -EPIPE; - } - - /* Setup reception buffer */ - g_request.buffer = address; - g_request.size = size; - client_state_change(BUFFERS_READY); - - /* Unlock write of data */ - complete(&g_request.client_complete); - - /* Wait for data (far too late to be interruptible) */ - wait_for_completion(&g_request.server_complete); - - /* Reset reception buffer */ - g_request.buffer = NULL; - g_request.size = 0; - - /* Return to idle state */ - client_state_change(IDLE); - return 0; -} - -/* Must be called instead of request_receive() to cancel a pending request */ -static void request_cancel(void) -{ - /* Unlock write of data */ - mutex_lock(&g_request.states_mutex); - if (g_request.server_state == DATA_SENT) - complete(&g_request.client_complete); - - /* Return to idle state */ - g_request.client_state = IDLE; - mutex_unlock(&g_request.states_mutex); -} - -static int admin_get_root_container(void *address) -{ - struct device *dev = g_admin_ctx.dev; - int ret = 0; - - /* Lock communication channel */ - mutex_lock(&g_request.mutex); - - /* Send request and wait for header */ - ret = request_send(MC_DRV_GET_ROOT_CONTAINER, 0, 0, 0); - if (ret) - goto end; - - /* Check length against max */ - if (g_request.response.length >= MAX_SO_CONT_SIZE) { - request_cancel(); - dev_err(dev, "%s: response length exceeds maximum\n", __func__); - ret = EREMOTEIO; - goto end; - } - - /* Get data */ - ret = request_receive(address, g_request.response.length); - if (!ret) - ret = g_request.response.length; - -end: - mutex_unlock(&g_request.mutex); - return ret; -} - -static int admin_get_sp_container(void *address, uint32_t spid) -{ - struct device *dev = g_admin_ctx.dev; - int ret = 0; - - /* Lock communication channel */ - mutex_lock(&g_request.mutex); - - /* Send request and wait for header */ - ret = request_send(MC_DRV_GET_SP_CONTAINER, 0, 0, spid); - if (ret) - goto end; - - /* Check length against max */ - if (g_request.response.length >= MAX_SO_CONT_SIZE) { - request_cancel(); - dev_err(dev, "%s: response length exceeds maximum\n", __func__); - ret = EREMOTEIO; - goto end; - } - - /* Get data */ - ret = request_receive(address, g_request.response.length); - if (!ret) - ret = g_request.response.length; - -end: - mutex_unlock(&g_request.mutex); - return ret; -} - -static int admin_get_trustlet_container(void *address, - const struct mc_uuid_t *uuid, - uint32_t spid) -{ - struct device *dev = g_admin_ctx.dev; - int ret = 0; - - /* Lock communication channel */ - mutex_lock(&g_request.mutex); - - /* Send request and wait for header */ - ret = request_send(MC_DRV_GET_TRUSTLET_CONTAINER, uuid, 0, spid); - if (ret) - goto end; - - /* Check length against max */ - if (g_request.response.length >= MAX_SO_CONT_SIZE) { - request_cancel(); - dev_err(dev, "%s: response length exceeds maximum\n", __func__); - ret = EREMOTEIO; - goto end; - } - - /* Get data */ - ret = request_receive(address, g_request.response.length); - if (!ret) - ret = g_request.response.length; - -end: - mutex_unlock(&g_request.mutex); - return ret; -} - -static struct tbase_object *admin_get_trustlet(const struct mc_uuid_t *uuid, - uint32_t is_gp, uint32_t *spid) -{ - struct tbase_object *obj = NULL; - bool is_sp_tl; - int ret = 0; - - /* Lock communication channel */ - mutex_lock(&g_request.mutex); - - /* Send request and wait for header */ - ret = request_send(MC_DRV_GET_TRUSTLET, uuid, is_gp, 0); - if (ret) - goto end; - - /* Allocate memory */ - is_sp_tl = g_request.response.service_type == SERVICE_TYPE_SP_TRUSTLET; - obj = tbase_object_alloc(is_sp_tl, g_request.response.length); - if (!obj) { - request_cancel(); - ret = -ENOMEM; - goto end; - } - - /* Get data */ - ret = request_receive(&obj->data[obj->header_length], obj->length); - *spid = g_request.response.spid; - -end: - mutex_unlock(&g_request.mutex); - if (ret) - return ERR_PTR(ret); - - return obj; -} - -static void mc_admin_sendcrashdump(void) -{ - int ret = 0; - - /* Lock communication channel */ - mutex_lock(&g_request.mutex); - - /* Send request and wait for header */ - ret = request_send(MC_DRV_SIGNAL_CRASH, NULL, false, 0); - if (ret) - goto end; - - /* Done */ - request_cancel(); - -end: - mutex_unlock(&g_request.mutex); -} - -static int tbase_object_make(uint32_t spid, struct tbase_object *obj) -{ - struct mc_blob_len_info *l_info = (struct mc_blob_len_info *)obj->data; - uint8_t *address = &obj->data[obj->header_length + obj->length]; - struct mclf_header_v2 *thdr; - int ret; - - /* Get root container */ - ret = admin_get_root_container(address); - if (ret < 0) - goto err; - - l_info->root_size = ret; - address += ret; - - /* Get SP container */ - ret = admin_get_sp_container(address, spid); - if (ret < 0) - goto err; - - l_info->sp_size = ret; - address += ret; - - /* Get trustlet container */ - thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; - ret = admin_get_trustlet_container(address, &thdr->uuid, spid); - if (ret < 0) - goto err; - - l_info->ta_size = ret; - address += ret; - - /* Setup lengths information */ - l_info->magic = MC_TLBLOBLEN_MAGIC; - obj->length += sizeof(*l_info); - obj->length += l_info->root_size + l_info->sp_size + l_info->ta_size; - ret = 0; - -err: - return ret; -} - -struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address, - size_t length) -{ - struct device *dev = g_admin_ctx.dev; - char __user *addr = (char __user *)address; - struct tbase_object *obj; - uint8_t *data; - struct mclf_header_v2 thdr; - int ret; - - /* Check length */ - if (length < sizeof(thdr)) { - dev_err(dev, "%s: buffer shorter than header size\n", __func__); - return ERR_PTR(-EFAULT); - } - - /* Read header */ - if (copy_from_user(&thdr, addr, sizeof(thdr))) { - dev_err(dev, "%s: header: copy_from_user failed\n", __func__); - return ERR_PTR(-EFAULT); - } - - /* Allocate memory */ - obj = tbase_object_alloc(thdr.service_type == SERVICE_TYPE_SP_TRUSTLET, - length); - if (!obj) - return ERR_PTR(-ENOMEM); - - /* Copy header */ - data = &obj->data[obj->header_length]; - memcpy(data, &thdr, sizeof(thdr)); - /* Copy the rest of the data */ - data += sizeof(thdr); - if (copy_from_user(data, &addr[sizeof(thdr)], length - sizeof(thdr))) { - dev_err(dev, "%s: data: copy_from_user failed\n", __func__); - vfree(obj); - return ERR_PTR(-EFAULT); - } - - if (obj->header_length) { - ret = tbase_object_make(spid, obj); - if (ret) { - vfree(obj); - return ERR_PTR(ret); - } - } - - return obj; -} - -struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid) -{ - struct tbase_object *obj; - struct mclf_header_v2 *thdr; - - obj = tbase_object_alloc(false, sizeof(*thdr)); - if (!obj) - return ERR_PTR(-ENOMEM); - - thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; - memcpy(&thdr->uuid, uuid, sizeof(thdr->uuid)); - return obj; -} - -struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid, - uint32_t is_gp_uuid) -{ - struct tbase_object *obj; - uint32_t spid = 0; - - /* admin_get_trustlet creates the right object based on service type */ - obj = admin_get_trustlet(uuid, is_gp_uuid, &spid); - if (IS_ERR(obj)) - return obj; - - /* SP trustlet: create full secure object with all containers */ - if (obj->header_length) { - int ret; - - /* Do not return EINVAL in this case as SPID was not found */ - if (!spid) { - vfree(obj); - return ERR_PTR(-ENOENT); - } - - ret = tbase_object_make(spid, obj); - if (ret) { - vfree(obj); - return ERR_PTR(ret); - } - } - - return obj; -} - -static inline int load_driver(struct tbase_client *client, - struct mc_admin_load_info *info) -{ - struct tbase_object *obj; - struct mclf_header_v2 *thdr; - struct mc_identity identity = { - .login_type = TEEC_LOGIN_PUBLIC, - }; - uintptr_t dci = 0; - uint32_t dci_len = 0; - uint32_t sid; - int ret; - - obj = tbase_object_read(info->spid, info->address, info->length); - if (IS_ERR(obj)) - return PTR_ERR(obj); - - thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; - if (!(thdr->flags & MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE)) { - /* - * The driver requires a DCI, although we won't be able to use - * it to communicate. - */ - dci_len = PAGE_SIZE; - ret = api_malloc_cbuf(client, dci_len, &dci, NULL); - if (ret) - goto end; - } - - /* Open session */ - ret = client_add_session(client, obj, dci, dci_len, &sid, false, - &identity); - if (ret) - api_free_cbuf(client, dci); - else - dev_dbg(g_admin_ctx.dev, "driver loaded with sid %x", sid); - -end: - vfree(obj); - return ret; -} - -static inline int load_token(struct mc_admin_load_info *token) -{ - struct tbase_mmu *mmu; - struct mcp_buffer_map map; - int ret; - - mmu = tbase_mmu_create(current, (void *)(uintptr_t)token->address, - token->length); - if (IS_ERR(mmu)) - return PTR_ERR(mmu); - - tbase_mmu_buffer(mmu, &map); - ret = mcp_load_token(token->address, &map); - tbase_mmu_delete(mmu); - return ret; -} - -static inline int load_check(struct mc_admin_load_info *info) -{ - struct tbase_object *obj; - struct tbase_mmu *mmu; - struct mcp_buffer_map map; - int ret; - - obj = tbase_object_read(info->spid, info->address, info->length); - if (IS_ERR(obj)) - return PTR_ERR(obj); - - mmu = tbase_mmu_create(NULL, obj->data, obj->length); - if (IS_ERR(mmu)) - return PTR_ERR(mmu); - - tbase_mmu_buffer(mmu, &map); - ret = mcp_load_check(obj, &map); - tbase_mmu_delete(mmu); - return ret; -} - -static ssize_t admin_write(struct file *file, const char __user *user, - size_t len, loff_t *off) -{ - int ret; - - /* No offset allowed [yet] */ - if (*off) { - g_request.response.error_no = EPIPE; - ret = -ECOMM; - goto err; - } - - if (server_state_is(REQUEST_RECEIVED)) { - /* Check client state */ - if (!client_state_is(REQUEST_SENT)) { - g_request.response.error_no = EPIPE; - ret = -EPIPE; - goto err; - } - - /* Receive response header */ - if (copy_from_user(&g_request.response, user, - sizeof(g_request.response))) { - g_request.response.error_no = EPIPE; - ret = -ECOMM; - goto err; - } - - /* Check request ID */ - if (g_request.request.request_id != - g_request.response.request_id) { - g_request.response.error_no = EPIPE; - ret = -EBADE; - goto err; - } - - /* Response header is acceptable */ - ret = sizeof(g_request.response); - if (g_request.response.length) - server_state_change(RESPONSE_SENT); - else - server_state_change(READY); - - goto end; - } else if (server_state_is(RESPONSE_SENT)) { - /* Server is waiting */ - server_state_change(DATA_SENT); - - /* Get data */ - ret = wait_for_completion_interruptible( - &g_request.client_complete); - - /* Server received a signal, let see if it tries again */ - if (ret) { - server_state_change(RESPONSE_SENT); - return ret; - } - - /* Check client state */ - if (!client_state_is(BUFFERS_READY)) { - g_request.response.error_no = EPIPE; - ret = -EPIPE; - goto err; - } - - /* TODO deal with several writes */ - if (len != g_request.size) - len = g_request.size; - - ret = copy_from_user(g_request.buffer, user, len); - if (ret) { - g_request.response.error_no = EPIPE; - ret = -ECOMM; - goto err; - } - - ret = len; - server_state_change(READY); - goto end; - } else { - ret = -ECOMM; - goto err; - } - -err: - server_state_change(READY); -end: - complete(&g_request.server_complete); - return ret; -} - -static long admin_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct tbase_client *client = file->private_data; - void __user *uarg = (void __user *)arg; - int ret = -EINVAL; - - MCDRV_DBG("%u from %s", _IOC_NR(cmd), current->comm); - - if (WARN(!client, "No client data available")) - return -EFAULT; - - switch (cmd) { - case MC_ADMIN_IO_GET_DRIVER_REQUEST: { - /* Block until a request is available */ - ret = wait_for_completion_interruptible( - &g_request.client_complete); - if (ret) - /* Interrupted by signal */ - break; - - /* Check client state */ - if (!client_state_is(REQUEST_SENT)) { - g_request.response.error_no = EPIPE; - complete(&g_request.server_complete); - ret = -EPIPE; - break; - } - - /* Send request (the driver request mutex is held) */ - ret = copy_to_user(uarg, &g_request.request, - sizeof(g_request.request)); - if (ret) { - server_state_change(READY); - complete(&g_request.server_complete); - ret = -EPROTO; - break; - } - - server_state_change(REQUEST_RECEIVED); - break; - } - case MC_ADMIN_IO_GET_INFO: { - struct mc_admin_driver_info info; - - info.drv_version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR, - MCDRVMODULEAPI_VERSION_MINOR); - info.initial_cmd_id = g_request.request_id; - ret = copy_to_user(uarg, &info, sizeof(info)); - break; - } - case MC_ADMIN_IO_LOAD_DRIVER: { - struct mc_admin_load_info info; - - ret = copy_from_user(&info, uarg, sizeof(info)); - if (ret) - ret = -EFAULT; - else - ret = load_driver(client, &info); - - break; - } - case MC_ADMIN_IO_LOAD_TOKEN: { - struct mc_admin_load_info info; - - ret = copy_from_user(&info, uarg, sizeof(info)); - if (ret) - ret = -EFAULT; - else - ret = load_token(&info); - - break; - } - case MC_ADMIN_IO_LOAD_CHECK: { - struct mc_admin_load_info info; - - ret = copy_from_user(&info, uarg, sizeof(info)); - if (ret) - ret = -EFAULT; - else - ret = load_check(&info); - - break; - } - default: - ret = -ENOIOCTLCMD; - } - - return ret; -} - -/* - * mc_fd_release() - This function will be called from user space as close(...) - * The client data are freed and the associated memory pages are unreserved. - * - * @inode - * @file - * - * Returns 0 - */ -static int admin_release(struct inode *inode, struct file *file) -{ - struct tbase_client *client = file->private_data; - struct device *dev = g_admin_ctx.dev; - - if (!client) - return -EPROTO; - - api_close_device(client); - file->private_data = NULL; - - /* Requests from driver to daemon */ - mutex_lock(&g_request.states_mutex); - dev_warn(dev, "%s: daemon disconnected\n", __func__); - g_request.server_state = NOT_CONNECTED; - /* A non-zero command indicates that a thread is waiting */ - if (g_request.client_state != IDLE) { - g_request.response.error_no = ESHUTDOWN; - complete(&g_request.server_complete); - } - - mutex_unlock(&g_request.states_mutex); - atomic_set(&g_admin_ctx.daemon_counter, 0); - /* - * ret is quite irrelevant here as most apps don't care about the - * return value from close() and it's quite difficult to recover - */ - return 0; -} - -static int admin_open(struct inode *inode, struct file *file) -{ - struct device *dev = g_admin_ctx.dev; - struct tbase_client *client; - int err; - - /* - * If the daemon is already set we can't allow anybody else to open - * the admin interface. - */ - if (atomic_cmpxchg(&g_admin_ctx.daemon_counter, 0, 1) != 0) { - MCDRV_ERROR("Daemon is already connected"); - return -EPROTO; - } - - /* Any value will do */ - g_request.request_id = 42; - - /* Setup the usual variables */ - MCDRV_DBG("accept %s as tbase daemon", current->comm); - - /* - * daemon is connected so now we can safely suppose - * the secure world is loaded too - */ - if (!IS_ERR_OR_NULL(g_admin_ctx.tee_start_cb)) - g_admin_ctx.tee_start_cb = ERR_PTR(g_admin_ctx.tee_start_cb()); - if (IS_ERR(g_admin_ctx.tee_start_cb)) { - MCDRV_ERROR("Failed initializing the SW"); - err = PTR_ERR(g_admin_ctx.tee_start_cb); - goto fail_connection; -} - - /* Create client */ - client = api_open_device(true); - if (!client) { - err = -ENOMEM; - goto fail_connection; - } - - /* Store client in user file */ - file->private_data = client; - - /* Requests from driver to daemon */ - server_state_change(READY); - dev_info(dev, "%s: daemon connected\n", __func__); - - return 0; - -fail_connection: - atomic_set(&g_admin_ctx.daemon_counter, 0); - return err; -} - -/* function table structure of this device driver. */ -static const struct file_operations mc_admin_fops = { - .owner = THIS_MODULE, - .open = admin_open, - .release = admin_release, - .unlocked_ioctl = admin_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = admin_ioctl, -#endif - .write = admin_write, -}; - -int mc_admin_init(struct class *mc_device_class, dev_t *out_dev, - int (*tee_start_cb)(void)) -{ - int err = 0; - - if (!out_dev || !mc_device_class) - return -EINVAL; - - atomic_set(&g_admin_ctx.daemon_counter, 0); - - /* Requests from driver to daemon */ - mutex_init(&g_request.mutex); - mutex_init(&g_request.states_mutex); - init_completion(&g_request.client_complete); - init_completion(&g_request.server_complete); - mcp_register_crashhandler(mc_admin_sendcrashdump); - - /* Create char device */ - cdev_init(&g_admin_ctx.mc_admin_cdev, &mc_admin_fops); - err = alloc_chrdev_region(&g_admin_ctx.mc_dev_admin, 0, MC_DEV_MAX, - "trustonic_tee"); - if (err < 0) { - MCDRV_ERROR("failed to allocate char dev region"); - goto fail_alloc_chrdev_region; - } - - err = cdev_add(&g_admin_ctx.mc_admin_cdev, g_admin_ctx.mc_dev_admin, 1); - if (err) { - MCDRV_ERROR("admin device register failed"); - goto fail_cdev_add; - } - - g_admin_ctx.mc_admin_cdev.owner = THIS_MODULE; - g_admin_ctx.dev = device_create(mc_device_class, NULL, - g_admin_ctx.mc_dev_admin, NULL, - MC_ADMIN_DEVNODE); - if (IS_ERR(g_admin_ctx.dev)) { - err = PTR_ERR(g_admin_ctx.dev); - goto fail_dev_create; - } - - g_admin_ctx.mc_dev_name.name = "driver = &g_admin_ctx.mc_dev_name; - *out_dev = g_admin_ctx.mc_dev_admin; - - /* Register the call back for starting the secure world */ - g_admin_ctx.tee_start_cb = tee_start_cb; - - MCDRV_DBG("done"); - return 0; - -fail_dev_create: - cdev_del(&g_admin_ctx.mc_admin_cdev); - -fail_cdev_add: - unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX); - -fail_alloc_chrdev_region: - MCDRV_ERROR("fail with %d", err); - return err; -} - -void mc_admin_exit(struct class *mc_device_class) -{ - device_destroy(mc_device_class, g_admin_ctx.mc_dev_admin); - cdev_del(&g_admin_ctx.mc_admin_cdev); - unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX); - /* Requests from driver to daemon */ - mutex_destroy(&g_request.states_mutex); - MCDRV_DBG("done"); -} diff --git a/drivers/gud/MobiCoreDriver/admin.h b/drivers/gud/MobiCoreDriver/admin.h deleted file mode 100644 index 5a78d943752da..0000000000000 --- a/drivers/gud/MobiCoreDriver/admin.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef ADMIN_FD_H_ -#define ADMIN_FD_H_ - -struct mc_uuid_t; -struct tbase_object; - -int mc_admin_init(struct class *mc_device_class, dev_t *out_dev, - int (*tee_start_cb)(void)); -void mc_admin_exit(struct class *mc_device_class); - -struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid); -struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid, - uint32_t is_gp_uuid); -struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address, - size_t length); -void tbase_object_free(struct tbase_object *out_robj); - -#endif /* ADMIN_FD_H_ */ diff --git a/drivers/gud/MobiCoreDriver/api.c b/drivers/gud/MobiCoreDriver/api.c deleted file mode 100644 index 0d2abaf617aea..0000000000000 --- a/drivers/gud/MobiCoreDriver/api.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include - -#include /* MC_MAP_MAX */ -#include "main.h" -#include "debug.h" -#include "mcp.h" -#include "admin.h" -#include "session.h" -#include "client.h" -#include "api.h" - -static struct api_ctx { - struct mutex clients_lock; /* Clients list + temp notifs */ - struct list_head clients; /* List of user-space clients */ -} api_ctx; - -/* - * Initialize a new tbase client object - * @return client pointer or NULL if no allocation was possible. - */ -struct tbase_client *api_open_device(bool is_from_kernel) -{ - struct tbase_client *client; - - /* Allocate and init client object */ - client = client_create(is_from_kernel); - if (!client) { - MCDRV_ERROR("Could not create client"); - return NULL; - } - - /* Add client to list of clients */ - mutex_lock(&api_ctx.clients_lock); - list_add_tail(&client->list, &api_ctx.clients); - mutex_unlock(&api_ctx.clients_lock); - - MCDRV_DBG("created client %p", client); - return client; -} - -/* - * Try and mark client as "closing" - * @return tbase driver error code - */ -int api_freeze_device(struct tbase_client *client) -{ - int err = 0; - - if (!client_set_closing(client)) - err = -ENOTEMPTY; - - MCDRV_DBG("client %p, exit with %d\n", client, err); - return err; -} - -/* - * Release a client and the session+cbuf objects it contains. - * @param client_t client - * @return tbase driver error code - */ -void api_close_device(struct tbase_client *client) -{ - /* Remove client from list of active clients */ - mutex_lock(&api_ctx.clients_lock); - list_del(&client->list); - mutex_unlock(&api_ctx.clients_lock); - /* Close all remaining sessions */ - client_close_sessions(client); - client_put(client); - MCDRV_DBG("client %p closed\n", client); -} - -/* - * Open TA for given client. TA binary is provided by the daemon. - * @param - * @return tbase driver error code - */ -int api_open_session(struct tbase_client *client, - uint32_t *p_session_id, - const struct mc_uuid_t *uuid, - uintptr_t tci, - size_t tci_len, - bool is_gp_uuid, - struct mc_identity *identity) -{ - int err = 0; - uint32_t sid = 0; - struct tbase_object *obj; - - /* Check parameters */ - if (!p_session_id) - return -EINVAL; - - if (!uuid) - return -EINVAL; - - /* Get secure object */ - obj = tbase_object_get(uuid, is_gp_uuid); - if (IS_ERR(obj)) { - /* Try to select secure object inside the SWd if not found */ - if ((PTR_ERR(obj) == -ENOENT) && g_ctx.f_ta_auth) - obj = tbase_object_select(uuid); - - if (IS_ERR(obj)) { - err = PTR_ERR(obj); - goto end; - } - } - - /* Open session */ - err = client_add_session(client, obj, tci, tci_len, &sid, is_gp_uuid, - identity); - /* Fill in return parameter */ - if (!err) - *p_session_id = sid; - - /* Delete secure object */ - tbase_object_free(obj); - -end: - - MCDRV_DBG("session %x, exit with %d\n", sid, err); - return err; -} - -/* - * Open TA for given client. TA binary is provided by the client. - * @param - * @return tbase driver error code - */ -int api_open_trustlet(struct tbase_client *client, - uint32_t *p_session_id, - uint32_t spid, - uintptr_t trustlet, - size_t trustlet_len, - uintptr_t tci, - size_t tci_len) -{ - struct tbase_object *obj; - struct mc_identity identity = { - .login_type = TEEC_LOGIN_PUBLIC, - }; - uint32_t sid = 0; - int err = 0; - - /* Check parameters */ - if (!p_session_id) - return -EINVAL; - - /* Create secure object from user-space trustlet binary */ - obj = tbase_object_read(spid, trustlet, trustlet_len); - if (IS_ERR(obj)) { - err = PTR_ERR(obj); - goto end; - } - - /* Open session */ - err = client_add_session(client, obj, tci, tci_len, &sid, false, - &identity); - /* Fill in return parameter */ - if (!err) - *p_session_id = sid; - - /* Delete secure object */ - tbase_object_free(obj); - -end: - MCDRV_DBG("session %x, exit with %d\n", sid, err); - return err; -} - -/* - * Close a TA - * @param - * @return tbase driver error code - */ -int api_close_session(struct tbase_client *client, uint32_t session_id) -{ - int ret = client_remove_session(client, session_id); - - MCDRV_DBG("session %x, exit with %d\n", session_id, ret); - return ret; -} - -/* - * Send a notification to TA - * @return tbase driver error code - */ -int api_notify(struct tbase_client *client, uint32_t session_id) -{ - int err = 0; - struct tbase_session *session = NULL; - - /* Acquire session */ - session = client_ref_session(client, session_id); - - /* Send command to SWd */ - if (!session) { - err = -ENXIO; - } else { - err = session_notify_swd(session); - - /* Release session */ - client_unref_session(session); - } - - MCDRV_DBG("session %x, exit with %d\n", session_id, err); - return err; -} - -/* - * Wait for a notification from TA - * @return tbase driver error code - */ -int api_wait_notification(struct tbase_client *client, - uint32_t session_id, - int32_t timeout) -{ - int err = 0; - struct tbase_session *session = NULL; - - /* Acquire session */ - session = client_ref_session(client, session_id); - - /* Wait for notification */ - if (!session) { - err = -ENXIO; - } else { - err = session_waitnotif(session, timeout); - - /* Release session */ - client_unref_session(session); - } - - MCDRV_DBG("session %x, exit with %d\n", session_id, err); - return err; -} - -/* - * Allocate a contiguous buffer (cbuf) for given client - * - * @param client client - * @param len size of the cbuf - * @param **p_addr pointer to the cbuf kva - * @return tbase driver error code - */ -int api_malloc_cbuf(struct tbase_client *client, uint32_t len, - uintptr_t *addr, struct vm_area_struct *vmarea) -{ - int err = tbase_cbuf_alloc(client, len, addr, vmarea); - - MCDRV_DBG("exit with %d\n", err); - return err; -} - -/* - * Free a contiguous buffer from given client - * @param client - * @param addr kernel virtual address of the buffer - * - * @return tbase driver error code - */ -int api_free_cbuf(struct tbase_client *client, uintptr_t addr) -{ - int err = tbase_cbuf_free(client, addr); - - MCDRV_DBG("@ 0x%lx, exit with %d\n", addr, err); - return err; -} - -/* Share a buffer with given TA in SWd */ -int api_map_wsms(struct tbase_client *client, uint32_t session_id, - struct mc_ioctl_buffer *bufs) -{ - struct tbase_session *session = NULL; - int err = 0; - - if (!client) - return -EINVAL; - - if (!bufs) - return -EINVAL; - - /* Acquire session */ - session = client_ref_session(client, session_id); - - if (session) { - /* Add buffer to the session */ - err = session_wsms_add(session, bufs); - - /* Release session */ - client_unref_session(session); - } else { - err = -ENXIO; - } - - MCDRV_DBG("exit with %d\n", err); - return err; -} - -/* Stop sharing a buffer with SWd */ -int api_unmap_wsms(struct tbase_client *client, uint32_t session_id, - const struct mc_ioctl_buffer *bufs) -{ - struct tbase_session *session = NULL; - int err = 0; - - if (!client) - return -EINVAL; - - if (!bufs) - return -EINVAL; - - /* Acquire session */ - session = client_ref_session(client, session_id); - - if (!session) { - err = -ENXIO; - } else { - /* Remove buffer from session */ - err = session_wsms_remove(session, bufs); - /* Release session */ - client_unref_session(session); - } - - MCDRV_DBG("exit with %d\n", err); - return err; -} - -/* - * Read session exit/termination code - */ -int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id, - int32_t *exit_code) -{ - int err = 0; - struct tbase_session *session; - - /* Acquire session */ - session = client_ref_session(client, session_id); - - if (!session) { - err = -ENXIO; - } else { - /* Retrieve error */ - *exit_code = session_exitcode(session); - - /* Release session */ - client_unref_session(session); - - err = 0; - } - - MCDRV_DBG("session %x, exit with %d\n", session_id, err); - return err; -} - -void api_init(void) -{ - INIT_LIST_HEAD(&api_ctx.clients); - mutex_init(&api_ctx.clients_lock); - - INIT_LIST_HEAD(&g_ctx.closing_sess); - mutex_init(&g_ctx.closing_lock); -} - -int api_info(struct kasnprintf_buf *buf) -{ - struct tbase_client *client; - struct tbase_session *session; - ssize_t ret = 0; - - mutex_lock(&api_ctx.clients_lock); - if (list_empty(&api_ctx.clients)) - goto done; - - list_for_each_entry(client, &api_ctx.clients, list) { - ret = client_info(client, buf); - if (ret < 0) - break; - } - -done: - mutex_unlock(&api_ctx.clients_lock); - - if (ret >= 0) { - mutex_lock(&g_ctx.closing_lock); - if (!list_empty(&g_ctx.closing_sess)) - ret = kasnprintf(buf, "closing sessions:\n"); - - list_for_each_entry(session, &g_ctx.closing_sess, list) { - ret = session_info(session, buf); - if (ret < 0) - break; - } - - mutex_unlock(&g_ctx.closing_lock); - } - - return ret; -} diff --git a/drivers/gud/MobiCoreDriver/api.h b/drivers/gud/MobiCoreDriver/api.h deleted file mode 100644 index 740ec7fb2d5b9..0000000000000 --- a/drivers/gud/MobiCoreDriver/api.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _API_H_ -#define _API_H_ - -struct tbase_client; - -struct tbase_client *api_open_device(bool is_from_kernel); -int api_freeze_device(struct tbase_client *client); -void api_close_device(struct tbase_client *client); -int api_open_session(struct tbase_client *client, uint32_t *session_id, - const struct mc_uuid_t *uuid, - uintptr_t tci, size_t tci_len, bool is_gp_uuid, - struct mc_identity *identity); -int api_open_trustlet(struct tbase_client *client, uint32_t *session_id, - uint32_t spid, uintptr_t trustlet, size_t trustlet_len, - uintptr_t tci, size_t tci_len); -int api_close_session(struct tbase_client *client, uint32_t session_id); -int api_notify(struct tbase_client *client, uint32_t session_id); -int api_wait_notification(struct tbase_client *client, uint32_t session_id, - int32_t timeout); -int api_malloc_cbuf(struct tbase_client *client, uint32_t len, uintptr_t *addr, - struct vm_area_struct *vmarea); -int api_free_cbuf(struct tbase_client *client, uintptr_t addr); -int api_map_wsms(struct tbase_client *client, uint32_t session_id, - struct mc_ioctl_buffer *bufs); -int api_unmap_wsms(struct tbase_client *client, uint32_t session_id, - const struct mc_ioctl_buffer *bufs); -int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id, - int32_t *exit_code); -void api_init(void); -int api_info(struct kasnprintf_buf *buf); - -#endif /* _API_H_ */ diff --git a/drivers/gud/MobiCoreDriver/arm.h b/drivers/gud/MobiCoreDriver/arm.h deleted file mode 100644 index 58d91f11f789c..0000000000000 --- a/drivers/gud/MobiCoreDriver/arm.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MC_ARM_H_ -#define _MC_ARM_H_ - -#include "debug.h" - -#ifdef CONFIG_ARM64 -inline bool has_security_extensions(void) -{ - return true; -} - -inline bool is_secure_mode(void) -{ - return false; -} -#else -/* - * ARM Trustzone specific masks and modes - * Vanilla Linux is unaware of TrustZone extension. - * I.e. arch/arm/include/asm/ptrace.h does not define monitor mode. - * Also TZ bits in cpuid are not defined, ARM port uses magic numbers, - * see arch/arm/kernel/setup.c - */ -#define ARM_MONITOR_MODE (0x16) /*(0b10110)*/ -#define ARM_SECURITY_EXTENSION_MASK (0x30) - -/* check if CPU supports the ARM TrustZone Security Extensions */ -inline bool has_security_extensions(void) -{ - u32 fea = 0; - - asm volatile( - "mrc p15, 0, %[fea], cr0, cr1, 0" : - [fea]"=r" (fea)); - - MCDRV_DBG_VERBOSE("CPU Features: 0x%X", fea); - - /* - * If the CPU features ID has 0 for security features then the CPU - * doesn't support TrustZone at all! - */ - if ((fea & ARM_SECURITY_EXTENSION_MASK) == 0) - return false; - - return true; -} - -/* check if running in secure mode */ -inline bool is_secure_mode(void) -{ - u32 cpsr = 0; - u32 nsacr = 0; - - asm volatile( - "mrc p15, 0, %[nsacr], cr1, cr1, 2\n" - "mrs %[cpsr], cpsr\n" : - [nsacr]"=r" (nsacr), - [cpsr]"=r"(cpsr)); - - MCDRV_DBG_VERBOSE("CPRS.M = set to 0x%X\n", cpsr & MODE_MASK); - MCDRV_DBG_VERBOSE("SCR.NS = set to 0x%X\n", nsacr); - - /* - * If the NSACR contains the reset value(=0) then most likely we are - * running in Secure MODE. - * If the cpsr mode is set to monitor mode then we cannot load! - */ - if (nsacr == 0 || ((cpsr & MODE_MASK) == ARM_MONITOR_MODE)) - return true; - - return false; -} -#endif - -#endif /* _MC_ARM_H_ */ diff --git a/drivers/gud/MobiCoreDriver/build_tag.h b/drivers/gud/MobiCoreDriver/build_tag.h deleted file mode 100644 index 51a5d3e0ae7f5..0000000000000 --- a/drivers/gud/MobiCoreDriver/build_tag.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#define MOBICORE_COMPONENT_BUILD_TAG \ - "t-base-QC-MSM8996-Android-302B-V001-20150529_084320_16" diff --git a/drivers/gud/MobiCoreDriver/client.c b/drivers/gud/MobiCoreDriver/client.c deleted file mode 100644 index c8bdc07b8742d..0000000000000 --- a/drivers/gud/MobiCoreDriver/client.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_admin.h" - -#include "main.h" -#include "debug.h" -#include "mcp.h" -#include "mmu.h" -#include "session.h" -#include "client.h" - -/* - * Contiguous buffer allocated to TLCs. - * These buffers are used as world shared memory (wsm) to share with - * secure world. - */ -struct tbase_cbuf { - /* Client this cbuf belongs to */ - struct tbase_client *client; - /* List element for client's list of cbuf's */ - struct list_head list; - /* Number of references kept to this buffer */ - struct kref kref; - /* virtual Kernel start address */ - uintptr_t addr; - /* virtual Userspace start address */ - uintptr_t uaddr; - /* physical start address */ - phys_addr_t phys; - /* 2^order = number of pages allocated */ - unsigned int order; - /* Length of memory mapped to user */ - uint32_t len; -}; - -/* - * Map a kernel contiguous buffer to user space - */ -static int map_cbuf(struct vm_area_struct *vmarea, uintptr_t addr, uint32_t len, - uintptr_t *uaddr) -{ - int ret; - - if (WARN(!uaddr, "No uaddr pointer available")) - return -EINVAL; - - if (WARN(!vmarea, "No vma available")) - return -EINVAL; - - if (WARN(!addr, "No addr available")) - return -EINVAL; - - if (len != (uint32_t)(vmarea->vm_end - vmarea->vm_start)) { - MCDRV_ERROR("cbuf incompatible with vma"); - return -EINVAL; - } - - vmarea->vm_flags |= VM_IO; - - /* CPI todo: use io_remap_page_range() to be consistent with VM_IO ? */ - ret = remap_pfn_range(vmarea, vmarea->vm_start, - page_to_pfn(virt_to_page(addr)), - vmarea->vm_end - vmarea->vm_start, - vmarea->vm_page_prot); - if (ret) { - *uaddr = 0; - MCDRV_ERROR("User mapping failed"); - return ret; - } - - *uaddr = vmarea->vm_start; - return 0; -} - -/* - * Allocate and initialize a client object - */ -struct tbase_client *client_create(bool is_from_kernel) -{ - struct tbase_client *client; - - /* allocate client structure */ - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) { - MCDRV_ERROR("Allocation failure"); - return NULL; - } - - /* init members */ - client->pid = is_from_kernel ? 0 : current->pid; - memcpy(client->comm, current->comm, sizeof(client->comm)); - kref_init(&client->kref); - INIT_LIST_HEAD(&client->cbufs); - mutex_init(&client->cbufs_lock); - INIT_LIST_HEAD(&client->sessions); - mutex_init(&client->sessions_lock); - INIT_LIST_HEAD(&client->list); - - return client; -} - -/* - * At this point, nobody has access to the client anymore, so no new sessions - * are coming. - */ -void client_close_sessions(struct tbase_client *client) -{ - struct tbase_session *session; - - mutex_lock(&client->sessions_lock); - while (!list_empty(&client->sessions)) { - session = list_first_entry(&client->sessions, - struct tbase_session, list); - - /* Move session to closing sessions list */ - mutex_lock(&g_ctx.closing_lock); - list_move(&session->list, &g_ctx.closing_sess); - mutex_unlock(&g_ctx.closing_lock); - /* Call session_close without lock */ - mutex_unlock(&client->sessions_lock); - session_close(session); - mutex_lock(&client->sessions_lock); - } - - mutex_unlock(&client->sessions_lock); -} - -/* - * Free client object + all objects it contains. - * Can be called only by last user referencing the client, - * therefore mutex lock seems overkill - */ -static void client_release(struct kref *kref) -{ - struct tbase_client *client; - - client = container_of(kref, struct tbase_client, kref); - kfree(client); -} - -void client_put(struct tbase_client *client) -{ - kref_put(&client->kref, client_release); -} - -/* - * Returns true if client is a kernel object. - */ -bool client_is_kernel(struct tbase_client *client) -{ - return !client->pid; -} - -/* - * Set client "closing" state, only if it contains no session. - * Once in "closing" state, system "close" can be called. - * Return: true if this state could be set. - */ -bool client_set_closing(struct tbase_client *client) -{ - bool clear = false; - - /* Check for sessions */ - mutex_lock(&client->sessions_lock); - clear = list_empty(&client->sessions); - client->closing = clear; - mutex_unlock(&client->sessions_lock); - MCDRV_DBG("return %d", clear); - return clear; -} - -/* - * Opens a TA and add corresponding session object to given client - * return: t-base driver error code - */ -int client_add_session(struct tbase_client *client, - const struct tbase_object *obj, uintptr_t tci, - size_t len, uint32_t *session_id, bool is_gp, - struct mc_identity *identity) -{ - struct tbase_session *session = NULL; - struct tbase_mmu *obj_mmu = NULL; - int ret = 0; - - /* - * Create session object with temp sid=0 BEFORE session is started, - * otherwise if a GP TA is started and NWd session object allocation - * fails, we cannot handle the potentially delayed GP closing. - * Adding session to list must be done AFTER it is started (once we have - * sid), therefore it cannot be done within session_create(). - */ - session = session_create(client, is_gp, identity); - if (IS_ERR(session)) - return PTR_ERR(session); - - /* Create blob L2 table (blob is allocated by driver, so task=NULL) */ - obj_mmu = tbase_mmu_create(NULL, obj->data, obj->length); - if (IS_ERR(obj_mmu)) { - ret = PTR_ERR(obj_mmu); - goto err; - } - - /* Open session */ - ret = session_open(session, obj, obj_mmu, tci, len); - /* Blob table no more needed in any case */ - tbase_mmu_delete(obj_mmu); - if (ret) - goto err; - - mutex_lock(&client->sessions_lock); - if (unlikely(client->closing)) { - /* Client has been frozen, no more sessions allowed */ - ret = -ENODEV; - } else { - /* Add session to client */ - list_add(&session->list, &client->sessions); - /* Set sid returned by SWd */ - *session_id = session->mcp_session.id; - } - - mutex_unlock(&client->sessions_lock); - -err: - /* Close or free session on error */ - if (ret == -ENODEV) { - /* The session must enter the closing process... */ - mutex_lock(&g_ctx.closing_lock); - list_add(&session->list, &g_ctx.closing_sess); - mutex_unlock(&g_ctx.closing_lock); - session_close(session); - } else if (ret) { - session_put(session); - } - - return ret; -} - -/* - * Remove a session object from client and close corresponding TA - * Return: true if session was found and closed - */ -int client_remove_session(struct tbase_client *client, uint32_t session_id) -{ - struct tbase_session *session = NULL, *candidate; - - /* Move session from main list to closing list */ - mutex_lock(&client->sessions_lock); - list_for_each_entry(candidate, &client->sessions, list) { - if (candidate->mcp_session.id == session_id) { - session = candidate; - mutex_lock(&g_ctx.closing_lock); - list_move(&session->list, &g_ctx.closing_sess); - mutex_unlock(&g_ctx.closing_lock); - break; - } - } - - mutex_unlock(&client->sessions_lock); - - /* Close session */ - return session_close(session); -} - -/* - * Find a session object and increment its reference counter. - * Object cannot be freed until its counter reaches 0. - * return: pointer to the object, NULL if not found. - */ -struct tbase_session *client_ref_session(struct tbase_client *client, - uint32_t session_id) -{ - struct tbase_session *session = NULL, *candidate; - - mutex_lock(&client->sessions_lock); - list_for_each_entry(candidate, &client->sessions, list) { - if (candidate->mcp_session.id == session_id) { - session = candidate; - session_get(session); - break; - } - } - - mutex_unlock(&client->sessions_lock); - return session; -} - -/* - * Decrement a session object's reference counter, and frees the object if it - * was the last reference. - * No lookup since session may have been removed from list - */ -void client_unref_session(struct tbase_session *session) -{ - session_put(session); -} - -static inline int cbuf_info(struct tbase_cbuf *cbuf, - struct kasnprintf_buf *buf); - -int client_info(struct tbase_client *client, struct kasnprintf_buf *buf) -{ - struct tbase_cbuf *cbuf; - struct tbase_session *session; - int ret; - - if (client->pid) - ret = kasnprintf(buf, "client %p: %s (%d)\n", client, - client->comm, client->pid); - else - ret = kasnprintf(buf, "client %p: [kernel]\n", client); - - if (ret < 0) - return ret; - - /* Buffers */ - mutex_lock(&client->cbufs_lock); - if (list_empty(&client->cbufs)) - goto done_cbufs; - - list_for_each_entry(cbuf, &client->cbufs, list) { - ret = cbuf_info(cbuf, buf); - if (ret < 0) - goto done_cbufs; - } - -done_cbufs: - mutex_unlock(&client->cbufs_lock); - if (ret < 0) - return ret; - - /* Sessions */ - mutex_lock(&client->sessions_lock); - if (list_empty(&client->sessions)) - goto done_sessions; - - list_for_each_entry(session, &client->sessions, list) { - ret = session_info(session, buf); - if (ret < 0) - goto done_sessions; - } - -done_sessions: - mutex_unlock(&client->sessions_lock); - - if (ret < 0) - return ret; - - return 0; -} - -/* - * This callback is called on remap - */ -static void cbuf_vm_open(struct vm_area_struct *vmarea) -{ - struct tbase_cbuf *cbuf = vmarea->vm_private_data; - - tbase_cbuf_get(cbuf); -} - -/* - * This callback is called on unmap - */ -static void cbuf_vm_close(struct vm_area_struct *vmarea) -{ - struct tbase_cbuf *cbuf = vmarea->vm_private_data; - - tbase_cbuf_put(cbuf); -} - -static struct vm_operations_struct cbuf_vm_ops = { - .open = cbuf_vm_open, - .close = cbuf_vm_close, -}; - -/* - * Create a cbuf object and add it to client - */ -int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len, - uintptr_t *p_addr, - struct vm_area_struct *vmarea) -{ - int err = 0; - struct tbase_cbuf *cbuf = NULL; - unsigned int order; - - if (WARN(!client, "No client available")) - return -EINVAL; - - if (WARN(!len, "No len available")) - return -EINVAL; - - order = get_order(len); - if (order > MAX_ORDER) { - MCDRV_DBG_WARN("Buffer size too large"); - return -ENOMEM; - } - - /* Allocate buffer descriptor structure */ - cbuf = kzalloc(sizeof(*cbuf), GFP_KERNEL); - if (!cbuf) { - MCDRV_DBG_WARN("kzalloc failed"); - return -ENOMEM; - } - - /* Allocate buffer */ - cbuf->addr = __get_free_pages(GFP_USER | __GFP_ZERO, order); - if (!cbuf->addr) { - MCDRV_DBG_WARN("get_free_pages failed"); - kfree(cbuf); - return -ENOMEM; - } - - /* Map to user space if applicable */ - if (!client_is_kernel(client)) { - err = map_cbuf(vmarea, cbuf->addr, len, &cbuf->uaddr); - if (err) { - free_pages(cbuf->addr, order); - kfree(cbuf); - return err; - } - } - - /* Init descriptor members */ - cbuf->client = client; - cbuf->phys = virt_to_phys((void *)cbuf->addr); - cbuf->len = len; - cbuf->order = order; - kref_init(&cbuf->kref); - INIT_LIST_HEAD(&cbuf->list); - - /* Keep cbuf in VMA private data for refcounting (user-space clients) */ - if (vmarea) { - vmarea->vm_private_data = cbuf; - vmarea->vm_ops = &cbuf_vm_ops; - } - - /* Fill return parameter for k-api */ - if (p_addr) - *p_addr = cbuf->addr; - - /* Get a token on the client */ - client_get(client); - - /* Add buffer to list */ - mutex_lock(&client->cbufs_lock); - list_add(&cbuf->list, &client->cbufs); - mutex_unlock(&client->cbufs_lock); - MCDRV_DBG("created cbuf %p: client %p addr %lx uaddr %lx len %u", - cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len); - return err; -} - -/* - * Remove a cbuf object from client, and mark it for freeing. - * Freeing will happen once all current references are released. - */ -int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr) -{ - struct tbase_cbuf *cbuf = tbase_cbuf_get_by_addr(client, addr); - - if (!cbuf) - return -EINVAL; - - /* Two references to put: the caller's and the one we just took */ - tbase_cbuf_put(cbuf); - tbase_cbuf_put(cbuf); - return 0; -} - -/* - * Find a contiguous buffer (cbuf) in the cbuf list of given client that - * contains given address and take a reference on it. - * Return pointer to the object, or NULL if not found. - */ -struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client, - uintptr_t addr) -{ - struct tbase_cbuf *cbuf = NULL, *candidate; - bool is_kernel = client_is_kernel(client); - - mutex_lock(&client->cbufs_lock); - list_for_each_entry(candidate, &client->cbufs, list) { - /* Compare Vs kernel va OR user va depending on client type */ - uintptr_t start = is_kernel ? - candidate->addr : candidate->uaddr; - uintptr_t end = start + candidate->len; - - /* Check that (user) cbuf has not been unmapped */ - if (!start) - break; - - if ((addr >= start) && (addr < end)) { - cbuf = candidate; - break; - } - } - - if (cbuf) - tbase_cbuf_get(cbuf); - - mutex_unlock(&client->cbufs_lock); - return cbuf; -} - -void tbase_cbuf_get(struct tbase_cbuf *cbuf) -{ - kref_get(&cbuf->kref); -} - -static void cbuf_release(struct kref *kref) -{ - struct tbase_cbuf *cbuf = container_of(kref, struct tbase_cbuf, kref); - struct tbase_client *client = cbuf->client; - - /* Unlist from client */ - mutex_lock(&client->cbufs_lock); - list_del_init(&cbuf->list); - mutex_unlock(&client->cbufs_lock); - /* Release client token */ - client_put(client); - /* Free */ - free_pages(cbuf->addr, cbuf->order); - MCDRV_DBG("freed cbuf %p: client %p addr %lx uaddr %lx len %u", - cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len); - kfree(cbuf); -} - -void tbase_cbuf_put(struct tbase_cbuf *cbuf) -{ - kref_put(&cbuf->kref, cbuf_release); -} - -uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf) -{ - return cbuf->addr; -} - -uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf) -{ - return cbuf->uaddr; -} - -uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf) -{ - return cbuf->len; -} - -static inline int cbuf_info(struct tbase_cbuf *cbuf, struct kasnprintf_buf *buf) -{ - return kasnprintf(buf, "\tcbuf %p: addr %lx uaddr %lx len %u\n", - cbuf, cbuf->addr, cbuf->uaddr, cbuf->len); -} diff --git a/drivers/gud/MobiCoreDriver/client.h b/drivers/gud/MobiCoreDriver/client.h deleted file mode 100644 index 3cc833eeffb87..0000000000000 --- a/drivers/gud/MobiCoreDriver/client.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _CLIENT_H_ -#define _CLIENT_H_ - -#include -#include /* TASK_COMM_LEN */ - -struct task_struct; -struct tbase_object; -struct tbase_session; - -struct tbase_client { - /* PID of task that opened the device, 0 if kernel */ - pid_t pid; - /* Command for task*/ - char comm[TASK_COMM_LEN]; - /* Number of references kept to this object */ - struct kref kref; - /* List of contiguous buffers allocated by mcMallocWsm for the client */ - struct list_head cbufs; - struct mutex cbufs_lock; /* lock for the cbufs list */ - /* List of tbase TA sessions opened by this client */ - struct list_head sessions; - struct mutex sessions_lock; /* sessions list + closing */ - /* Client state */ - bool closing; - /* The list entry to attach to "ctx.clients" list */ - struct list_head list; -}; - -struct tbase_client *client_create(bool is_from_kernel); - -void client_close_sessions(struct tbase_client *client); - -static inline void client_get(struct tbase_client *client) -{ - kref_get(&client->kref); -} - -void client_put(struct tbase_client *client); - -bool client_is_kernel(struct tbase_client *client); - -bool client_set_closing(struct tbase_client *client); - -int client_add_session(struct tbase_client *client, - const struct tbase_object *obj, uintptr_t tci, - size_t len, uint32_t *p_sid, bool is_gp_uuid, - struct mc_identity *identity); - -int client_remove_session(struct tbase_client *client, uint32_t session_id); - -struct tbase_session *client_ref_session(struct tbase_client *client, - uint32_t session_id); - -void client_unref_session(struct tbase_session *session); - -int client_info(struct tbase_client *client, struct kasnprintf_buf *buf); - -/* - * Contiguous buffer allocated to TLCs. - * These buffers are uses as world shared memory (wsm) and shared with - * secure world. - * The virtual kernel address is added for a simpler search algorithm. - */ -struct tbase_cbuf; - -int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len, - uintptr_t *addr, struct vm_area_struct *vmarea); - -int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr); - -struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client, - uintptr_t addr); - -void tbase_cbuf_get(struct tbase_cbuf *cbuf); - -void tbase_cbuf_put(struct tbase_cbuf *cbuf); - -uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf); - -uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf); - -uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf); - -#endif /* _CLIENT_H_ */ diff --git a/drivers/gud/MobiCoreDriver/clientlib.c b/drivers/gud/MobiCoreDriver/clientlib.c deleted file mode 100644 index c7d6d023b3a80..0000000000000 --- a/drivers/gud/MobiCoreDriver/clientlib.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_admin.h" -#include "public/mobicore_driver_api.h" - -#include "main.h" -#include "debug.h" -#include "client.h" -#include "session.h" -#include "api.h" - -enum mc_result convert(int err) -{ - switch (-err) { - case 0: - return MC_DRV_OK; - case ENOMSG: - return MC_DRV_NO_NOTIFICATION; - case EBADMSG: - return MC_DRV_ERR_NOTIFICATION; - case EAGAIN: - return MC_DRV_ERR_OUT_OF_RESOURCES; - case EHOSTDOWN: - return MC_DRV_ERR_INIT; - case ENODEV: - return MC_DRV_ERR_UNKNOWN_DEVICE; - case ENXIO: - return MC_DRV_ERR_UNKNOWN_SESSION; - case EPERM: - return MC_DRV_ERR_INVALID_OPERATION; - case EBADE: - return MC_DRV_ERR_INVALID_RESPONSE; - case ETIME: - return MC_DRV_ERR_TIMEOUT; - case ENOMEM: - return MC_DRV_ERR_NO_FREE_MEMORY; - case EUCLEAN: - return MC_DRV_ERR_FREE_MEMORY_FAILED; - case ENOTEMPTY: - return MC_DRV_ERR_SESSION_PENDING; - case EHOSTUNREACH: - return MC_DRV_ERR_DAEMON_UNREACHABLE; - case ENOENT: - return MC_DRV_ERR_INVALID_DEVICE_FILE; - case EINVAL: - return MC_DRV_ERR_INVALID_PARAMETER; - case EPROTO: - return MC_DRV_ERR_KERNEL_MODULE; - case EADDRINUSE: - return MC_DRV_ERR_BULK_MAPPING; - case EADDRNOTAVAIL: - return MC_DRV_ERR_BULK_UNMAPPING; - case ECOMM: - return MC_DRV_INFO_NOTIFICATION; - case EUNATCH: - return MC_DRV_ERR_NQ_FAILED; - default: - MCDRV_DBG("error is %d", err); - return MC_DRV_ERR_UNKNOWN; - } -} - -static inline bool is_valid_device(uint32_t device_id) -{ - return MC_DEVICE_ID_DEFAULT == device_id; -} - -static struct tbase_client *client; -static int open_count; -static DEFINE_MUTEX(dev_mutex); /* Lock for the device */ - -static bool clientlib_client_get(void) -{ - int ret = true; - - mutex_lock(&dev_mutex); - if (!client) - ret = false; - else - client_get(client); - - mutex_unlock(&dev_mutex); - return ret; -} - -static void clientlib_client_put(void) -{ - mutex_lock(&dev_mutex); - client_put(client); - mutex_unlock(&dev_mutex); -} - -enum mc_result mc_open_device(uint32_t device_id) -{ - enum mc_result mc_result = MC_DRV_OK; - - /* Check parameters */ - if (!is_valid_device(device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - mutex_lock(&dev_mutex); - if (!open_count) - client = api_open_device(true); - - if (client) { - open_count++; - MCDRV_DBG("Successfully opened the device."); - } else { - mc_result = MC_DRV_ERR_INVALID_DEVICE_FILE; - MCDRV_DBG("Could not open device"); - } - - mutex_unlock(&dev_mutex); - return mc_result; -} -EXPORT_SYMBOL(mc_open_device); - -enum mc_result mc_close_device(uint32_t device_id) -{ - enum mc_result mc_result = MC_DRV_OK; - - /* Check parameters */ - if (!is_valid_device(device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - mutex_lock(&dev_mutex); - if (!client) { - mc_result = MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - goto end; - } - - if (open_count > 1) { - open_count--; - goto end; - } - - /* Check sessions and freeze client */ - mc_result = convert(api_freeze_device(client)); - if (MC_DRV_OK != mc_result) - goto end; - - /* Close the device */ - api_close_device(client); - client = NULL; - open_count = 0; - -end: - mutex_unlock(&dev_mutex); - return mc_result; -} -EXPORT_SYMBOL(mc_close_device); - -enum mc_result mc_open_session(struct mc_session_handle *session, - const struct mc_uuid_t *uuid, - uint8_t *tci, uint32_t len) -{ - struct mc_identity identity = { - .login_type = TEEC_LOGIN_PUBLIC, - }; - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_open_session(client, &session->session_id, uuid, - (uintptr_t)tci, len, false, &identity)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_open_session); - -enum mc_result mc_open_trustlet(struct mc_session_handle *session, - uint32_t spid, - uint8_t *trustlet, uint32_t trustlet_len, - uint8_t *tci, uint32_t len) -{ - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_open_trustlet(client, &session->session_id, spid, - (uintptr_t)trustlet, trustlet_len, - (uintptr_t)tci, len)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_open_trustlet); - -enum mc_result mc_close_session(struct mc_session_handle *session) -{ - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_close_session(client, session->session_id)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_close_session); - -enum mc_result mc_notify(struct mc_session_handle *session) -{ - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_notify(client, session->session_id)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_notify); - -enum mc_result mc_wait_notification(struct mc_session_handle *session, - int32_t timeout) -{ - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_wait_notification(client, session->session_id, - timeout)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_wait_notification); - -enum mc_result mc_malloc_wsm(uint32_t device_id, uint32_t align, uint32_t len, - uint8_t **wsm, uint32_t wsm_flags) -{ - enum mc_result ret; - uintptr_t va; - - /* Check parameters */ - if (!is_valid_device(device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!len) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!wsm) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_malloc_cbuf(client, len, &va, NULL)); - if (ret == MC_DRV_OK) - *wsm = (uint8_t *)va; - - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_malloc_wsm); - -enum mc_result mc_free_wsm(uint32_t device_id, uint8_t *wsm) -{ - enum mc_result ret; - uintptr_t va = (uintptr_t)wsm; - - /* Check parameters */ - if (!is_valid_device(device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_free_cbuf(client, va)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_free_wsm); - -enum mc_result mc_map(struct mc_session_handle *session, void *address, - uint32_t length, struct mc_bulk_map *map_info) -{ - enum mc_result ret; - struct mc_ioctl_buffer bufs[MC_MAP_MAX]; - uint32_t i; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!map_info) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - bufs[0].va = (uintptr_t)address; - bufs[0].len = length; - for (i = 1; i < MC_MAP_MAX; i++) - bufs[i].va = 0; - - ret = convert(api_map_wsms(client, session->session_id, bufs)); - if (ret == MC_DRV_OK) { - map_info->secure_virt_addr = bufs[0].sva; - map_info->secure_virt_len = bufs[0].len; - } - - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_map); - -enum mc_result mc_unmap(struct mc_session_handle *session, void *address, - struct mc_bulk_map *map_info) -{ - enum mc_result ret; - struct mc_ioctl_buffer bufs[MC_MAP_MAX]; - uint32_t i; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!map_info) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - bufs[0].va = (uintptr_t)address; - bufs[0].len = map_info->secure_virt_len; - bufs[0].sva = map_info->secure_virt_addr; - for (i = 1; i < MC_MAP_MAX; i++) - bufs[i].va = 0; - - ret = convert(api_unmap_wsms(client, session->session_id, bufs)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_unmap); - -enum mc_result mc_get_session_error_code(struct mc_session_handle *session, - int32_t *exit_code) -{ - enum mc_result ret; - - /* Check parameters */ - if (!session) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!is_valid_device(session->device_id)) - return MC_DRV_ERR_UNKNOWN_DEVICE; - - if (!exit_code) - return MC_DRV_ERR_INVALID_PARAMETER; - - if (!clientlib_client_get()) - return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; - - /* Call core api */ - ret = convert(api_get_session_exitcode(client, session->session_id, - exit_code)); - clientlib_client_put(); - return ret; -} -EXPORT_SYMBOL(mc_get_session_error_code); diff --git a/drivers/gud/MobiCoreDriver/clock.c b/drivers/gud/MobiCoreDriver/clock.c deleted file mode 100644 index 0195ab794f205..0000000000000 --- a/drivers/gud/MobiCoreDriver/clock.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 "platform.h" - -#ifdef MC_CRYPTO_CLOCK_MANAGEMENT - -#include -#include -#include -#include - -#include "debug.h" -#include "clock.h" - -static struct clk_context { - struct clk *mc_ce_iface_clk; - struct clk *mc_ce_core_clk; - struct clk *mc_ce_bus_clk; - struct clk *mc_ce_core_src_clk; -} clk_ctx; - -int mc_clock_init(void) -{ - int ret = 0; -#ifdef MC_CLOCK_CORESRC_DEFAULTRATE - int core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE; - - /* Get core clk src */ - clk_ctx.mc_ce_core_src_clk = clk_get(g_ctx.mcd, "core_clk_src"); - if (IS_ERR(clk_ctx.mc_ce_core_src_clk)) { - ret = PTR_ERR(clk_ctx.mc_ce_core_src_clk); - MCDRV_ERROR("cannot get core src clock: %d", ret); - goto error; - } - -#ifdef MC_CRYPTO_CLOCK_CORESRC_PROPNAME - if (of_property_read_u32(g_ctx.mcd->of_node, - MC_CRYPTO_CLOCK_CORESRC_PROPNAME, - &core_src_rate)) { - core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE; - MCDRV_ERROR("cannot get ce clock frequency from DT, use %d", - core_src_rate); - } -#endif /* MC_CRYPTO_CLOCK_CORESRC_PROPNAME */ - - ret = clk_set_rate(clk_ctx.mc_ce_core_src_clk, core_src_rate); - if (ret) { - clk_put(clk_ctx.mc_ce_core_src_clk); - clk_ctx.mc_ce_core_src_clk = NULL; - MCDRV_ERROR("cannot set core clock src rate: %d", ret); - ret = -EIO; - goto error; - } -#endif /* MC_CLOCK_CORESRC_DEFAULTRATE */ - - /* Get core clk */ - clk_ctx.mc_ce_core_clk = clk_get(g_ctx.mcd, "core_clk"); - if (IS_ERR(clk_ctx.mc_ce_core_clk)) { - ret = PTR_ERR(clk_ctx.mc_ce_core_clk); - MCDRV_ERROR("cannot get core clock: %d", ret); - goto error; - } - /* Get Interface clk */ - clk_ctx.mc_ce_iface_clk = clk_get(g_ctx.mcd, "iface_clk"); - if (IS_ERR(clk_ctx.mc_ce_iface_clk)) { - clk_put(clk_ctx.mc_ce_core_clk); - ret = PTR_ERR(clk_ctx.mc_ce_iface_clk); - MCDRV_ERROR("cannot get iface clock: %d", ret); - goto error; - } - /* Get AXI clk */ - clk_ctx.mc_ce_bus_clk = clk_get(g_ctx.mcd, "bus_clk"); - if (IS_ERR(clk_ctx.mc_ce_bus_clk)) { - clk_put(clk_ctx.mc_ce_iface_clk); - clk_put(clk_ctx.mc_ce_core_clk); - ret = PTR_ERR(clk_ctx.mc_ce_bus_clk); - MCDRV_ERROR("cannot get AXI bus clock: %d", ret); - goto error; - } - return ret; - -error: - clk_ctx.mc_ce_core_clk = NULL; - clk_ctx.mc_ce_iface_clk = NULL; - clk_ctx.mc_ce_bus_clk = NULL; - clk_ctx.mc_ce_core_src_clk = NULL; - return ret; -} - -void mc_clock_exit(void) -{ - if (clk_ctx.mc_ce_iface_clk) - clk_put(clk_ctx.mc_ce_iface_clk); - - if (clk_ctx.mc_ce_core_clk) - clk_put(clk_ctx.mc_ce_core_clk); - - if (clk_ctx.mc_ce_bus_clk) - clk_put(clk_ctx.mc_ce_bus_clk); - - if (clk_ctx.mc_ce_core_src_clk) - clk_put(clk_ctx.mc_ce_core_src_clk); -} - -int mc_clock_enable(void) -{ - int rc; - - rc = clk_prepare_enable(clk_ctx.mc_ce_core_clk); - if (rc) { - MCDRV_ERROR("cannot enable core clock"); - goto err_core; - } - - rc = clk_prepare_enable(clk_ctx.mc_ce_iface_clk); - if (rc) { - MCDRV_ERROR("cannot enable interface clock"); - goto err_iface; - } - - rc = clk_prepare_enable(clk_ctx.mc_ce_bus_clk); - if (rc) { - MCDRV_ERROR("cannot enable bus clock"); - goto err_bus; - } - - return 0; - -err_bus: - clk_disable_unprepare(clk_ctx.mc_ce_iface_clk); -err_iface: - clk_disable_unprepare(clk_ctx.mc_ce_core_clk); -err_core: - return rc; -} - -void mc_clock_disable(void) -{ - if (clk_ctx.mc_ce_iface_clk) - clk_disable_unprepare(clk_ctx.mc_ce_iface_clk); - - if (clk_ctx.mc_ce_core_clk) - clk_disable_unprepare(clk_ctx.mc_ce_core_clk); - - if (clk_ctx.mc_ce_bus_clk) - clk_disable_unprepare(clk_ctx.mc_ce_bus_clk); -} - -#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */ diff --git a/drivers/gud/MobiCoreDriver/clock.h b/drivers/gud/MobiCoreDriver/clock.h deleted file mode 100644 index 21095499efb53..0000000000000 --- a/drivers/gud/MobiCoreDriver/clock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _MC_CLOCK_H_ -#define _MC_CLOCK_H_ - -#include "platform.h" /* MC_CRYPTO_CLOCK_MANAGEMENT */ - -#ifdef MC_CRYPTO_CLOCK_MANAGEMENT - -/* Initialize secure crypto clocks */ -int mc_clock_init(void); -/* Free secure crypto clocks */ -void mc_clock_exit(void); -/* Enable secure crypto clocks */ -int mc_clock_enable(void); -/* Disable secure crypto clocks */ -void mc_clock_disable(void); - -#else /* MC_CRYPTO_CLOCK_MANAGEMENT */ - -static inline int mc_clock_init(void) -{ - return 0; -} - -static inline void mc_clock_exit(void) -{ -} - -static inline int mc_clock_enable(void) -{ - return 0; -} - -static inline void mc_clock_disable(void) -{ -} - -#endif /* !MC_CRYPTO_CLOCK_MANAGEMENT */ - -#endif /* _MC_CLOCK_H_ */ diff --git a/drivers/gud/MobiCoreDriver/debug.h b/drivers/gud/MobiCoreDriver/debug.h deleted file mode 100644 index 9d6a52ab955b6..0000000000000 --- a/drivers/gud/MobiCoreDriver/debug.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MC_DEBUG_H_ -#define _MC_DEBUG_H_ - -#include "main.h" /* g_ctx */ - -#define MCDRV_ERROR(txt, ...) \ - dev_err(g_ctx.mcd, "%s() ### ERROR: " txt "\n", \ - __func__, \ - ##__VA_ARGS__) - -/* dummy function helper macro. */ -#define DUMMY_FUNCTION() do {} while (0) - -#ifdef DEBUG - -#ifdef DEBUG_VERBOSE -#define MCDRV_DBG_VERBOSE MCDRV_DBG -#else -#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION() -#endif - -#define MCDRV_DBG(txt, ...) \ - dev_info(g_ctx.mcd, "%s(): " txt "\n", \ - __func__, \ - ##__VA_ARGS__) - -#define MCDRV_DBG_WARN(txt, ...) \ - dev_warn(g_ctx.mcd, "%s() WARNING: " txt "\n", \ - __func__, \ - ##__VA_ARGS__) - -#define MCDRV_ASSERT(cond) \ - do { \ - if (unlikely(!(cond))) { \ - panic("Assertion failed: %s:%d\n", \ - __FILE__, __LINE__); \ - } \ - } while (0) - -#else /* DEBUG */ - -#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION() -#define MCDRV_DBG(...) DUMMY_FUNCTION() -#define MCDRV_DBG_WARN(...) DUMMY_FUNCTION() - -#define MCDRV_ASSERT(...) DUMMY_FUNCTION() - -#endif /* !DEBUG */ - -#endif /* _MC_DEBUG_H_ */ diff --git a/drivers/gud/MobiCoreDriver/fastcall.c b/drivers/gud/MobiCoreDriver/fastcall.c deleted file mode 100644 index ee612632331c8..0000000000000 --- a/drivers/gud/MobiCoreDriver/fastcall.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_linux_api.h" - -#include "mci/mcifc.h" - -#include "platform.h" /* MC_FASTCALL_WORKER_THREAD and more */ -#include "debug.h" -#include "clock.h" /* mc_clock_enable, mc_clock_disable */ -#include "fastcall.h" - -struct fastcall_work { -#ifdef MC_FASTCALL_WORKER_THREAD - struct kthread_work work; -#else - struct work_struct work; -#endif - void *data; -}; - -/* generic fast call parameters */ -union mc_fc_generic { - struct { - uint32_t cmd; - uint32_t param[3]; - } as_in; - struct { - uint32_t resp; - uint32_t ret; - uint32_t param[2]; - } as_out; -}; - -/* fast call init */ -union mc_fc_init { - union mc_fc_generic as_generic; - struct { - uint32_t cmd; - uint32_t base; - uint32_t nq_info; - uint32_t mcp_info; - } as_in; - struct { - uint32_t resp; - uint32_t ret; - uint32_t rfu[2]; - } as_out; -}; - -/* fast call info parameters */ -union mc_fc_info { - union mc_fc_generic as_generic; - struct { - uint32_t cmd; - uint32_t ext_info_id; - uint32_t rfu[2]; - } as_in; - struct { - uint32_t resp; - uint32_t ret; - uint32_t state; - uint32_t ext_info; - } as_out; -}; - -#ifdef TBASE_CORE_SWITCHER -/* fast call switch Core parameters */ -union mc_fc_swich_core { - union mc_fc_generic as_generic; - struct { - uint32_t cmd; - uint32_t core_id; - uint32_t rfu[2]; - } as_in; - struct { - uint32_t resp; - uint32_t ret; - uint32_t state; - uint32_t ext_info; - } as_out; -}; -#endif - -#ifdef MC_FASTCALL_WORKER_THREAD -static struct task_struct *fastcall_thread; -static DEFINE_KTHREAD_WORKER(fastcall_worker); -#endif - -/* - * _smc() - fast call to MobiCore - * - * @data: pointer to fast call data - */ -static inline int _smc(union mc_fc_generic *mc_fc_generic) -{ - if (!mc_fc_generic) - return -EINVAL; - -#ifdef MC_SMC_FASTCALL - return smc_fastcall(mc_fc_generic, sizeof(*mc_fc_generic)); -#else /* MC_SMC_FASTCALL */ - { -#ifdef CONFIG_ARM64 - /* SMC expect values in x0-x3 */ - register u64 reg0 __asm__("x0") = mc_fc_generic->as_in.cmd; - register u64 reg1 __asm__("x1") = mc_fc_generic->as_in.param[0]; - register u64 reg2 __asm__("x2") = mc_fc_generic->as_in.param[1]; - register u64 reg3 __asm__("x3") = mc_fc_generic->as_in.param[2]; - - /* - * According to AARCH64 SMC Calling Convention (ARM DEN 0028A), - * section 3.1: registers x4-x17 are unpredictable/scratch - * registers. So we have to make sure that the compiler does - * not allocate any of those registers by letting him know that - * the asm code might clobber them. - */ - __asm__ volatile ( - "smc #0\n" - : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) - : - : "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", - "x12", "x13", "x14", "x15", "x16", "x17" - ); -#else /* CONFIG_ARM64 */ - /* SMC expect values in r0-r3 */ - register u32 reg0 __asm__("r0") = mc_fc_generic->as_in.cmd; - register u32 reg1 __asm__("r1") = mc_fc_generic->as_in.param[0]; - register u32 reg2 __asm__("r2") = mc_fc_generic->as_in.param[1]; - register u32 reg3 __asm__("r3") = mc_fc_generic->as_in.param[2]; - - __asm__ volatile ( -#ifdef MC_ARCH_EXTENSION_SEC - /* This pseudo op is supported and required from - * binutils 2.21 on */ - ".arch_extension sec\n" -#endif /* MC_ARCH_EXTENSION_SEC */ - "smc #0\n" - : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) - ); - -#ifdef __ARM_VE_A9X4_QEMU__ - /* Qemu does not return to the address following the SMC - * instruction so we have to insert several nop instructions to - * workaround this Qemu bug. */ - __asm__ volatile ( - "nop\n" - "nop\n" - "nop\n" - "nop" - ); -#endif /* __ARM_VE_A9X4_QEMU__ */ -#endif /* !CONFIG_ARM64 */ - - /* set response */ - mc_fc_generic->as_out.resp = reg0; - mc_fc_generic->as_out.ret = reg1; - mc_fc_generic->as_out.param[0] = reg2; - mc_fc_generic->as_out.param[1] = reg3; - } - return 0; -#endif /* !MC_SMC_FASTCALL */ -} - -#ifdef TBASE_CORE_SWITCHER -static uint32_t active_cpu; - -#ifdef MC_FASTCALL_WORKER_THREAD -static void mc_cpu_offline(int cpu) -{ - int i; - - if (active_cpu != cpu) { - MCDRV_DBG("not active CPU, no action taken\n"); - return; - } - - /* Chose the first online CPU and switch! */ - for_each_online_cpu(i) { - if (cpu != i) { - MCDRV_DBG("CPU %d is dying, switching to %d\n", cpu, i); - mc_switch_core(i); - break; - } - - MCDRV_DBG("Skipping CPU %d\n", cpu); - } -} - -static int mobicore_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - - switch (action) { - case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - dev_info(g_ctx.mcd, "Cpu %u is going to die\n", cpu); - mc_cpu_offline(cpu); - break; - case CPU_DEAD: - case CPU_DEAD_FROZEN: - dev_info(g_ctx.mcd, "Cpu %u is dead\n", cpu); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block mobicore_cpu_notifer = { - .notifier_call = mobicore_cpu_callback, -}; -#endif /* MC_FASTCALL_WORKER_THREAD */ - -static cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) -{ - cpumask_t cpu; - uint32_t new_cpu; - uint32_t cpu_id[] = CPU_IDS; - - new_cpu = mc_fc_generic->as_in.param[0]; - mc_fc_generic->as_in.param[0] = cpu_id[mc_fc_generic->as_in.param[0]]; - - if (_smc(mc_fc_generic) != 0 || mc_fc_generic->as_out.ret != 0) { - MCDRV_DBG("CoreSwap failed %d -> %d (cpu %d still active)\n", - raw_smp_processor_id(), - mc_fc_generic->as_in.param[0], - raw_smp_processor_id()); - } else { - active_cpu = new_cpu; - MCDRV_DBG("CoreSwap ok %d -> %d\n", - raw_smp_processor_id(), active_cpu); - } - cpumask_clear(&cpu); - cpumask_set_cpu(active_cpu, &cpu); - return cpu; -} -#else /* TBASE_CORE_SWITCHER */ -static inline cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) -{ - return CPU_MASK_CPU0; -} -#endif /* !TBASE_CORE_SWITCHER */ - -#ifdef MC_FASTCALL_WORKER_THREAD -static void fastcall_work_func(struct kthread_work *work) -#else -static void fastcall_work_func(struct work_struct *work) -#endif -{ - struct fastcall_work *fc_work = - container_of(work, struct fastcall_work, work); - union mc_fc_generic *mc_fc_generic = fc_work->data; - - if (!mc_fc_generic) - return; - - mc_clock_enable(); - - if (mc_fc_generic->as_in.cmd == MC_FC_SWAP_CPU) { -#ifdef MC_FASTCALL_WORKER_THREAD - cpumask_t new_msk = mc_exec_core_switch(mc_fc_generic); - - set_cpus_allowed(fastcall_thread, new_msk); -#else - mc_exec_core_switch(mc_fc_generic); -#endif - } else { - _smc(mc_fc_generic); - } - - mc_clock_disable(); -} - -static bool mc_fastcall(void *data) -{ -#ifdef MC_FASTCALL_WORKER_THREAD - struct fastcall_work fc_work = { - KTHREAD_WORK_INIT(fc_work.work, fastcall_work_func), - .data = data, - }; - - if (!queue_kthread_work(&fastcall_worker, &fc_work.work)) - return false; - - /* If work is queued or executing, wait for it to finish execution */ - flush_kthread_work(&fc_work.work); -#else - struct fastcall_work fc_work = { - .data = data, - }; - - INIT_WORK_ONSTACK(&fc_work.work, fastcall_work_func); - - if (!schedule_work_on(0, &fc_work.work)) - return false; - - flush_work(&fc_work.work); -#endif - return true; -} - -int mc_fastcall_init(void) -{ - int ret = mc_clock_init(); - - if (ret) - return ret; - -#ifdef MC_FASTCALL_WORKER_THREAD - fastcall_thread = kthread_create(kthread_worker_fn, &fastcall_worker, - "mc_fastcall"); - if (IS_ERR(fastcall_thread)) { - ret = PTR_ERR(fastcall_thread); - fastcall_thread = NULL; - MCDRV_ERROR("cannot create fastcall wq (%d)", ret); - return ret; - } - - /* this thread MUST run on CPU 0 at startup */ - set_cpus_allowed(fastcall_thread, CPU_MASK_CPU0); - - wake_up_process(fastcall_thread); -#ifdef TBASE_CORE_SWITCHER - ret = register_cpu_notifier(&mobicore_cpu_notifer); -#endif -#endif /* MC_FASTCALL_WORKER_THREAD */ - return ret; -} - -void mc_fastcall_exit(void) -{ -#ifdef MC_FASTCALL_WORKER_THREAD - if (!IS_ERR_OR_NULL(fastcall_thread)) { -#ifdef TBASE_CORE_SWITCHER - unregister_cpu_notifier(&mobicore_cpu_notifer); -#endif - kthread_stop(fastcall_thread); - fastcall_thread = NULL; - } -#endif /* MC_FASTCALL_WORKER_THREAD */ - mc_clock_exit(); -} - -/* - * convert fast call return code to linux driver module error code - */ -static int convert_fc_ret(uint32_t ret) -{ - switch (ret) { - case MC_FC_RET_OK: - return 0; - case MC_FC_RET_ERR_INVALID: - return -EINVAL; - case MC_FC_RET_ERR_ALREADY_INITIALIZED: - return -EBUSY; - default: - return -EFAULT; - } -} - -int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len) -{ -#ifdef CONFIG_ARM64 - uint32_t base_high = (uint32_t)(base_pa >> 32); -#else - uint32_t base_high = 0; -#endif - union mc_fc_init fc_init; - - /* Call the INIT fastcall to setup MobiCore initialization */ - memset(&fc_init, 0, sizeof(fc_init)); - fc_init.as_in.cmd = MC_FC_INIT; - /* base address of mci buffer PAGE_SIZE (default is 4KB) aligned */ - fc_init.as_in.base = (uint32_t)base_pa; - /* notification buffer start/length [16:16] [start, length] */ - fc_init.as_in.nq_info = - ((base_high & 0xFFFF) << 16) | (q_len & 0xFFFF); - /* mcp buffer start/length [16:16] [start, length] */ - fc_init.as_in.mcp_info = (off << 16) | (buf_len & 0xFFFF); - MCDRV_DBG("cmd=0x%08x, base=0x%08x,nq_info=0x%08x, mcp_info=0x%08x", - fc_init.as_in.cmd, fc_init.as_in.base, fc_init.as_in.nq_info, - fc_init.as_in.mcp_info); - mc_fastcall(&fc_init.as_generic); - MCDRV_DBG("out cmd=0x%08x, ret=0x%08x", fc_init.as_out.resp, - fc_init.as_out.ret); - return convert_fc_ret(fc_init.as_out.ret); -} - -int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info) -{ - union mc_fc_info fc_info; - int ret = 0; - - memset(&fc_info, 0, sizeof(fc_info)); - fc_info.as_in.cmd = MC_FC_INFO; - fc_info.as_in.ext_info_id = ext_info_id; - mc_fastcall(&fc_info.as_generic); - ret = convert_fc_ret(fc_info.as_out.ret); - if (ret) { - if (state) - *state = MC_STATUS_NOT_INITIALIZED; - - if (ext_info) - *ext_info = 0; - - MCDRV_ERROR("code %d for idx %d", ret, ext_info_id); - } else { - if (state) - *state = fc_info.as_out.state; - - if (ext_info) - *ext_info = fc_info.as_out.ext_info; - } - - return ret; -} - -int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size) -{ - union mc_fc_generic mc_fc_generic; - - memset(&mc_fc_generic, 0, sizeof(mc_fc_generic)); - mc_fc_generic.as_in.cmd = MC_FC_MEM_TRACE; - mc_fc_generic.as_in.param[0] = (uint32_t)buffer; -#ifdef CONFIG_ARM64 - mc_fc_generic.as_in.param[1] = (uint32_t)(buffer >> 32); -#endif - mc_fc_generic.as_in.param[2] = size; - mc_fastcall(&mc_fc_generic); - return convert_fc_ret(mc_fc_generic.as_out.ret); -} - -int mc_fc_nsiq(void) -{ - union mc_fc_generic fc; - int ret; - - memset(&fc, 0, sizeof(fc)); - fc.as_in.cmd = MC_SMC_N_SIQ; - mc_fastcall(&fc); - ret = convert_fc_ret(fc.as_out.ret); - if (ret) - MCDRV_ERROR("failed: %d", ret); - - return ret; -} - -int mc_fc_yield(void) -{ - union mc_fc_generic fc; - int ret; - - memset(&fc, 0, sizeof(fc)); - fc.as_in.cmd = MC_SMC_N_YIELD; - mc_fastcall(&fc); - ret = convert_fc_ret(fc.as_out.ret); - if (ret) - MCDRV_ERROR("failed: %d", ret); - - return ret; -} - -#ifdef TBASE_CORE_SWITCHER -uint32_t mc_active_core(void) -{ - return active_cpu; -} - -int mc_switch_core(uint32_t core_num) -{ - int32_t ret = 0; - union mc_fc_swich_core fc_switch_core; - - if (!cpu_online(core_num)) - return 1; - - MCDRV_DBG_VERBOSE("enter\n"); - memset(&fc_switch_core, 0, sizeof(fc_switch_core)); - fc_switch_core.as_in.cmd = MC_FC_SWAP_CPU; - if (core_num < COUNT_OF_CPUS) - fc_switch_core.as_in.core_id = core_num; - else - fc_switch_core.as_in.core_id = 0; - - MCDRV_DBG("<- cmd=0x%08x, core_id=0x%08x\n", - fc_switch_core.as_in.cmd, fc_switch_core.as_in.core_id); - MCDRV_DBG("<- core_num=0x%08x, active_cpu=0x%08x\n", - core_num, active_cpu); - mc_fastcall(&fc_switch_core.as_generic); - ret = convert_fc_ret(fc_switch_core.as_out.ret); - MCDRV_DBG_VERBOSE("exit with %d/0x%08X\n", ret, ret); - return ret; -} -#endif diff --git a/drivers/gud/MobiCoreDriver/fastcall.h b/drivers/gud/MobiCoreDriver/fastcall.h deleted file mode 100644 index b19b27687ff38..0000000000000 --- a/drivers/gud/MobiCoreDriver/fastcall.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _TBASE_FASTCALL_H_ -#define _TBASE_FASTCALL_H_ - -/* Use the arch_extension sec pseudo op before switching to secure world */ -#if defined(__GNUC__) && \ - defined(__GNUC_MINOR__) && \ - defined(__GNUC_PATCHLEVEL__) && \ - ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)) \ - >= 40502 -#ifndef CONFIG_ARM64 -#define MC_ARCH_EXTENSION_SEC -#endif -#endif - -int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len); -int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info); -int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size); -int mc_fc_nsiq(void); -int mc_fc_yield(void); - -int mc_fastcall_init(void); -void mc_fastcall_exit(void); - -#endif /* _TBASE_FASTCALL_H_ */ diff --git a/drivers/gud/MobiCoreDriver/logging.c b/drivers/gud/MobiCoreDriver/logging.c deleted file mode 100644 index 953de5f149f78..0000000000000 --- a/drivers/gud/MobiCoreDriver/logging.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include - -#include "fastcall.h" -#include "main.h" -#include "logging.h" - -#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES - -/* Supported log buffer version */ -#define MC_LOG_VERSION 2 - -/* Default length of the log ring buffer 256KiB */ -#define LOG_BUF_ORDER 6 - -/* Max Len of a log line for printing */ -#define LOG_LINE_SIZE 256 - -/* Definitions for log version 2 */ -#define LOG_TYPE_MASK (0x0007) -#define LOG_TYPE_CHAR 0 -#define LOG_TYPE_INTEGER 1 - -/* Field length */ -#define LOG_LENGTH_MASK (0x00F8) -#define LOG_LENGTH_SHIFT 3 - -/* Extra attributes */ -#define LOG_EOL (0x0100) -#define LOG_INTEGER_DECIMAL (0x0200) -#define LOG_INTEGER_SIGNED (0x0400) - -struct mc_logmsg { - uint16_t ctrl; /* Type and format of data */ - uint16_t source; /* Unique value for each event source */ - uint32_t log_data; /* Value, if any */ -}; - -/* MobiCore internal trace buffer structure. */ -struct mc_trace_buf { - uint32_t version; /* version of trace buffer */ - uint32_t length; /* length of buff */ - uint32_t head; /* last write position */ - uint8_t buff[]; /* start of the log buffer */ -}; - -static struct logging_ctx { - struct work_struct work; - union { - struct mc_trace_buf *trace_buf; /* Circular log buffer */ - unsigned long trace_page; - }; - bool buffer_is_shared; /* Log buffer cannot be freed */ - uint32_t tail; /* MobiCore log read position */ - uint32_t line_len; /* Log Line buffer current length */ - int thread_err; - uint16_t prev_source; /* Previous Log source */ - char line[LOG_LINE_SIZE]; /* Log Line buffer */ - bool dead; -} log_ctx; - -static inline void log_eol(uint16_t source) -{ - if (!strnlen(log_ctx.line, LOG_LINE_SIZE)) { - /* In case a TA tries to print a 0x0 */ - log_ctx.line_len = 0; - return; - } - - if (log_ctx.prev_source) - /* MobiCore Userspace */ - dev_info(g_ctx.mcd, "%03x|%s\n", log_ctx.prev_source, - log_ctx.line); - else - /* MobiCore kernel */ - dev_info(g_ctx.mcd, "%s\n", log_ctx.line); - - log_ctx.line_len = 0; - log_ctx.line[0] = 0; -} - -/* - * Collect chars in log_ctx.line buffer and output the buffer when it is full. - * No locking needed because only "mobicore_log" thread updates this buffer. - */ -static inline void log_char(char ch, uint16_t source) -{ - if (ch == '\n' || ch == '\r') { - log_eol(source); - return; - } - - if ((log_ctx.line_len >= (LOG_LINE_SIZE - 1)) || - (source != log_ctx.prev_source)) - log_eol(source); - - log_ctx.line[log_ctx.line_len++] = ch; - log_ctx.line[log_ctx.line_len] = 0; - log_ctx.prev_source = source; -} - -static inline void log_string(uint32_t ch, uint16_t source) -{ - while (ch) { - log_char(ch & 0xFF, source); - ch >>= 8; - } -} - -static inline void log_number(uint32_t format, uint32_t value, uint16_t source) -{ - int width = (format & LOG_LENGTH_MASK) >> LOG_LENGTH_SHIFT; - char fmt[16]; - char buffer[32]; - const char *reader = buffer; - - if (format & LOG_INTEGER_DECIMAL) - if (format & LOG_INTEGER_SIGNED) - snprintf(fmt, sizeof(fmt), "%%%ud", width); - else - snprintf(fmt, sizeof(fmt), "%%%uu", width); - else - snprintf(fmt, sizeof(fmt), "%%0%ux", width); - - snprintf(buffer, sizeof(buffer), fmt, value); - while (*reader) - log_char(*reader++, source); -} - -static inline int log_msg(void *data) -{ - struct mc_logmsg *msg = (struct mc_logmsg *)data; - int log_type = msg->ctrl & LOG_TYPE_MASK; - - switch (log_type) { - case LOG_TYPE_CHAR: - log_string(msg->log_data, msg->source); - break; - case LOG_TYPE_INTEGER: - log_number(msg->ctrl, msg->log_data, msg->source); - break; - } - if (msg->ctrl & LOG_EOL) - log_eol(msg->source); - - return sizeof(*msg); -} - -static void log_worker(struct work_struct *work) -{ - while (log_ctx.trace_buf->head != log_ctx.tail) { - if (log_ctx.trace_buf->version != MC_LOG_VERSION) { - dev_err(g_ctx.mcd, - "Bad log data v%d (exp. v%d), stop.\n", - log_ctx.trace_buf->version, - MC_LOG_VERSION); - log_ctx.dead = true; - break; - } - - log_ctx.tail += log_msg(&log_ctx.trace_buf->buff[log_ctx.tail]); - /* Wrap over if no space left for a complete message */ - if ((log_ctx.tail + sizeof(struct mc_logmsg)) > - log_ctx.trace_buf->length) - log_ctx.tail = 0; - } -} - -/* - * Wake up the log reader thread - * This should be called from the places where calls into MobiCore have - * generated some logs(eg, yield, SIQ...) - */ -void mc_logging_run(void) -{ - if (!log_ctx.dead && (log_ctx.trace_buf->head != log_ctx.tail)) - schedule_work(&log_ctx.work); -} - -int mc_logging_start(void) -{ - int ret = mc_fc_mem_trace(virt_to_phys((void *)(log_ctx.trace_page)), - BIT(LOG_BUF_ORDER) * PAGE_SIZE); - - if (ret) { - dev_err(g_ctx.mcd, "shared traces setup failed\n"); - return ret; - } - - log_ctx.buffer_is_shared = true; - dev_dbg(g_ctx.mcd, "fc_log version %u\n", log_ctx.trace_buf->version); - mc_logging_run(); - return 0; -} - -void mc_logging_stop(void) -{ - if (!mc_fc_mem_trace(0, 0)) - log_ctx.buffer_is_shared = false; - - mc_logging_run(); - flush_work(&log_ctx.work); -} - -/* - * Setup MobiCore kernel log. It assumes it's running on CORE 0! - * The fastcall will complain is that is not the case! - */ -int mc_logging_init(void) -{ - /* - * We are going to map this buffer into virtual address space in SWd. - * To reduce complexity there, we use a contiguous buffer. - */ - log_ctx.trace_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, - LOG_BUF_ORDER); - if (!log_ctx.trace_page) - return -ENOMEM; - - INIT_WORK(&log_ctx.work, log_worker); - return 0; -} - -void mc_logging_exit(void) -{ - /* - * This is not racey as the only caller for mc_logging_run is the - * scheduler which gets stopped before us, and long before we exit. - */ - if (!log_ctx.buffer_is_shared) - free_pages(log_ctx.trace_page, LOG_BUF_ORDER); - else - dev_err(g_ctx.mcd, "log buffer unregister not supported\n"); -} - -#endif /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */ diff --git a/drivers/gud/MobiCoreDriver/logging.h b/drivers/gud/MobiCoreDriver/logging.h deleted file mode 100644 index 744b41880ea31..0000000000000 --- a/drivers/gud/MobiCoreDriver/logging.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MC_LOGGING_H_ -#define _MC_LOGGING_H_ - -#include "platform.h" /* CONFIG_TRUSTONIC_TEE_NO_TRACES */ - -/* MobiCore internal trace log setup. */ -#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES -void mc_logging_run(void); -int mc_logging_init(void); -void mc_logging_exit(void); -int mc_logging_start(void); -void mc_logging_stop(void); -#else /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */ -static inline void mc_logging_run(void) -{ -} - -static inline long mc_logging_init(void) -{ - return 0; -} - -static inline void mc_logging_exit(void) -{ -} - -static inline int mc_logging_start(void) -{ - return 0; -} - -static inline void mc_logging_stop(void) -{ -} - -#endif /* CONFIG_TRUSTONIC_TEE_NO_TRACES */ - -#endif /* _MC_LOGGING_H_ */ diff --git a/drivers/gud/MobiCoreDriver/main.c b/drivers/gud/MobiCoreDriver/main.c deleted file mode 100644 index 66b232e5bc8b5..0000000000000 --- a/drivers/gud/MobiCoreDriver/main.c +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" - -#include "main.h" -#include "fastcall.h" -#include "arm.h" -#include "mmu.h" -#include "scheduler.h" -#include "pm.h" -#include "debug.h" -#include "logging.h" -#include "admin.h" -#include "mcp.h" -#include "session.h" -#include "client.h" -#include "api.h" - -#include "build_tag.h" - -/* Define a MobiCore device structure for use with dev_debug() etc */ -static struct device_driver driver = { - .name = "Trustonic" -}; - -static struct device device = { - .driver = &driver -}; - -struct mc_device_ctx g_ctx = { - .mcd = &device -}; - -/* device admin */ -static dev_t mc_dev_admin; -/* device user */ -static dev_t mc_dev_user; - -/* Need to discover a chrdev region for the driver */ -static struct cdev mc_user_cdev; -/* Device class for the driver assigned major */ -static struct class *mc_device_class; - -/* - * Get client object from file pointer - */ -static inline struct tbase_client *get_client(struct file *file) -{ - return (struct tbase_client *)file->private_data; -} - -/* - * Callback for system mmap() - */ -static int mc_fd_user_mmap(struct file *file, struct vm_area_struct *vmarea) -{ - struct tbase_client *client = get_client(file); - uint32_t len = (uint32_t)(vmarea->vm_end - vmarea->vm_start); - - /* Alloc contiguous buffer for this client */ - return api_malloc_cbuf(client, len, NULL, vmarea); -} - -/* - * Check r/w access to referenced memory - */ -static inline int ioctl_check_pointer(unsigned int cmd, int __user *uarg) -{ - int err = 0; - - if (_IOC_DIR(cmd) & _IOC_READ) - err = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd)); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd)); - - if (err) - return -EFAULT; - - return 0; -} - -/* - * Callback for system ioctl() - * Implement most of ClientLib API functions - * @file pointer to file - * @cmd command - * @arg arguments - * - * Returns 0 for OK and an errno in case of error - */ -static long mc_fd_user_ioctl(struct file *file, unsigned int id, - unsigned long arg) -{ - struct tbase_client *client = get_client(file); - int __user *uarg = (int __user *)arg; - int ret = -EINVAL; - - MCDRV_DBG("%u from %s", _IOC_NR(id), current->comm); - - if (WARN(!client, "No client data available")) - return -EPROTO; - - if (ioctl_check_pointer(id, uarg)) - return -EFAULT; - - switch (id) { - case MC_IO_FREEZE: - /* Freeze the client */ - ret = api_freeze_device(client); - break; - - case MC_IO_OPEN_SESSION: { - struct mc_ioctl_open_sess sess; - - if (copy_from_user(&sess, uarg, sizeof(sess))) { - ret = -EFAULT; - break; - } - - ret = api_open_session(client, &sess.sid, &sess.uuid, sess.tci, - sess.tcilen, sess.is_gp_uuid, - &sess.identity); - if (ret) - break; - - if (copy_to_user(uarg, &sess, sizeof(sess))) { - ret = -EFAULT; - api_close_session(client, sess.sid); - break; - } - break; - } - case MC_IO_OPEN_TRUSTLET: { - struct mc_ioctl_open_trustlet ta_desc; - - if (copy_from_user(&ta_desc, uarg, sizeof(ta_desc))) { - ret = -EFAULT; - break; - } - - /* Call internal api */ - ret = api_open_trustlet(client, &ta_desc.sid, ta_desc.spid, - ta_desc.buffer, ta_desc.tlen, - ta_desc.tci, ta_desc.tcilen); - if (ret) - break; - - if (copy_to_user(uarg, &ta_desc, sizeof(ta_desc))) { - ret = -EFAULT; - api_close_session(client, ta_desc.sid); - break; - } - break; - } - case MC_IO_CLOSE_SESSION: { - uint32_t sid = (uint32_t)arg; - - ret = api_close_session(client, sid); - break; - } - case MC_IO_NOTIFY: { - uint32_t sid = (uint32_t)arg; - - ret = api_notify(client, sid); - break; - } - case MC_IO_WAIT: { - struct mc_ioctl_wait wait; - - if (copy_from_user(&wait, uarg, sizeof(wait))) { - ret = -EFAULT; - break; - } - ret = api_wait_notification(client, wait.sid, wait.timeout); - break; - } - case MC_IO_MAP: { - struct mc_ioctl_map map; - - if (copy_from_user(&map, uarg, sizeof(map))) { - ret = -EFAULT; - break; - } - ret = api_map_wsms(client, map.sid, map.bufs); - if (ret) - break; - - /* Fill in return struct */ - if (copy_to_user(uarg, &map, sizeof(map))) { - ret = -EFAULT; - api_unmap_wsms(client, map.sid, map.bufs); - break; - } - break; - } - case MC_IO_UNMAP: { - struct mc_ioctl_map map; - - if (copy_from_user(&map, uarg, sizeof(map))) { - ret = -EFAULT; - break; - } - - ret = api_unmap_wsms(client, map.sid, map.bufs); - break; - } - case MC_IO_ERR: { - struct mc_ioctl_geterr *uerr = (struct mc_ioctl_geterr *)uarg; - uint32_t sid; - int32_t exit_code; - - if (get_user(sid, &uerr->sid)) { - ret = -EFAULT; - break; - } - - ret = api_get_session_exitcode(client, sid, &exit_code); - if (ret) - break; - - /* Fill in return struct */ - if (put_user(exit_code, &uerr->value)) { - ret = -EFAULT; - break; - } - - break; - } - case MC_IO_VERSION: { - struct mc_version_info version_info; - - ret = mcp_get_version(&version_info); - if (ret) - break; - - if (copy_to_user(uarg, &version_info, sizeof(version_info))) - ret = -EFAULT; - - break; - } - case MC_IO_DR_VERSION: { - uint32_t version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR, - MCDRVMODULEAPI_VERSION_MINOR); - - ret = put_user(version, uarg); - break; - } - default: - MCDRV_ERROR("unsupported cmd=0x%x", id); - ret = -ENOIOCTLCMD; - } - - return ret; -} - -/* - * Callback for system open() - * A set of internal client data are created and initialized. - * - * @inode - * @file - * Returns 0 if OK or -ENOMEM if no allocation was possible. - */ -static int mc_fd_user_open(struct inode *inode, struct file *file) -{ - struct tbase_client *client; - - MCDRV_DBG("from %s", current->comm); - - /* Create client */ - client = api_open_device(false); - if (!client) - return -ENOMEM; - - /* Store client in user file */ - file->private_data = client; - return 0; -} - -/* - * Callback for system close() - * The client object is freed. - * @inode - * @file - * Returns 0 - */ -static int mc_fd_user_release(struct inode *inode, struct file *file) -{ - struct tbase_client *client = get_client(file); - - MCDRV_DBG("from %s", current->comm); - - if (WARN(!client, "No client data available")) - return -EPROTO; - - /* Detach client from user file */ - file->private_data = NULL; - - /* Destroy client, including remaining sessions */ - api_close_device(client); - return 0; -} - -static const struct file_operations mc_user_fops = { - .owner = THIS_MODULE, - .open = mc_fd_user_open, - .release = mc_fd_user_release, - .unlocked_ioctl = mc_fd_user_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mc_fd_user_ioctl, -#endif - .mmap = mc_fd_user_mmap, -}; - -int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...) -{ - va_list args; - int max_size = buf->size - buf->off; - int i; - - va_start(args, fmt); - i = vsnprintf(buf->buf + buf->off, max_size, fmt, args); - if (i >= max_size) { - int new_size = PAGE_ALIGN(buf->size + i + 1); - char *new_buf = krealloc(buf->buf, new_size, buf->gfp); - - if (!new_buf) { - i = -ENOMEM; - } else { - buf->buf = new_buf; - buf->size = new_size; - max_size = buf->size - buf->off; - i = vsnprintf(buf->buf + buf->off, max_size, fmt, args); - } - } - - if (i > 0) - buf->off += i; - - va_end(args); - return i; -} - -static ssize_t debug_info_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - /* Add/update buffer */ - if (!file->private_data || !*ppos) { - struct kasnprintf_buf *buf, *old_buf; - int ret; - - buf = kzalloc(GFP_KERNEL, sizeof(*buf)); - if (!buf) - return -ENOMEM; - - buf->gfp = GFP_KERNEL; - ret = api_info(buf); - if (ret < 0) { - kfree(buf); - return ret; - } - - old_buf = file->private_data; - file->private_data = buf; - kfree(old_buf); - } - - if (file->private_data) { - struct kasnprintf_buf *buf = file->private_data; - - return simple_read_from_buffer(user_buf, count, ppos, buf->buf, - buf->off); - } - - return 0; -} - -static int debug_info_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - return 0; -} - -static const struct file_operations mc_debug_info_ops = { - .read = debug_info_read, - .llseek = default_llseek, - .release = debug_info_release, -}; - -static inline int device_admin_init(int (*tee_start_cb)(void)) -{ - int ret = 0; - - cdev_init(&mc_user_cdev, &mc_user_fops); - - mc_device_class = class_create(THIS_MODULE, "trustonic_tee"); - if (IS_ERR(mc_device_class)) { - MCDRV_ERROR("failed to create device class"); - return PTR_ERR(mc_device_class); - } - - /* Create the ADMIN node */ - ret = mc_admin_init(mc_device_class, &mc_dev_admin, tee_start_cb); - if (ret < 0) { - MCDRV_ERROR("failed to init mobicore device"); - class_destroy(mc_device_class); - return ret; - } - return 0; -} - -static inline int device_user_init(void) -{ - int ret = 0; - struct device *dev; - - mc_dev_user = MKDEV(MAJOR(mc_dev_admin), 1); - /* Create the user node */ - ret = cdev_add(&mc_user_cdev, mc_dev_user, 1); - if (ret) { - MCDRV_ERROR("user device register failed"); - goto err_cdev_add; - } - mc_user_cdev.owner = THIS_MODULE; - dev = device_create(mc_device_class, NULL, mc_dev_user, NULL, - MC_USER_DEVNODE); - if (IS_ERR(dev)) { - ret = PTR_ERR(dev); - goto err_device_create; - } - - /* Create debugfs info entry */ - debugfs_create_file("info", 0400, g_ctx.debug_dir, NULL, - &mc_debug_info_ops); - - return 0; - -err_device_create: - cdev_del(&mc_user_cdev); -err_cdev_add: - mc_admin_exit(mc_device_class); - class_destroy(mc_device_class); - MCDRV_DBG("failed with %d", ret); - return ret; -} - -static void devices_exit(void) -{ - device_destroy(mc_device_class, mc_dev_user); - cdev_del(&mc_user_cdev); - mc_admin_exit(mc_device_class); - class_destroy(mc_device_class); -} - -static inline int mobicore_start(void) -{ - int ret; - struct mc_version_info version_info; - - ret = mcp_start(); - if (ret) { - MCDRV_ERROR("TEE start failed"); - goto err_mcp; - } - - ret = mc_logging_start(); - if (ret) { - MCDRV_ERROR("Log start failed"); - goto err_log; - } - - ret = mc_scheduler_start(); - if (ret) { - MCDRV_ERROR("Scheduler start failed"); - goto err_sched; - } - - ret = mc_pm_start(); - if (ret) { - MCDRV_ERROR("Power Management start failed"); - goto err_pm; - } - - ret = mcp_get_version(&version_info); - if (ret) - goto err_mcp_cmd; - - MCDRV_DBG("\n" - " product_id = %s\n" - " version_so = 0x%x\n" - " version_mci = 0x%x\n" - " version_mclf = 0x%x\n" - " version_container = 0x%x\n" - " version_mc_config = 0x%x\n" - " version_tl_api = 0x%x\n" - " version_dr_api = 0x%x\n" - " version_cmp = 0x%x\n", - version_info.product_id, - version_info.version_mci, - version_info.version_so, - version_info.version_mclf, - version_info.version_container, - version_info.version_mc_config, - version_info.version_tl_api, - version_info.version_dr_api, - version_info.version_cmp); - - if (MC_VERSION_MAJOR(version_info.version_mci) > 1) { - pr_err("MCI version %d.%d is too recent for this driver", - MC_VERSION_MAJOR(version_info.version_mci), - MC_VERSION_MINOR(version_info.version_mci)); - goto err_version; - } - - if ((MC_VERSION_MAJOR(version_info.version_mci) == 0) && - (MC_VERSION_MINOR(version_info.version_mci) < 6)) { - pr_err("MCI version %d.%d is too old for this driver", - MC_VERSION_MAJOR(version_info.version_mci), - MC_VERSION_MINOR(version_info.version_mci)); - goto err_version; - } - - dev_info(g_ctx.mcd, "MobiCore MCI version is %d.%d\n", - MC_VERSION_MAJOR(version_info.version_mci), - MC_VERSION_MINOR(version_info.version_mci)); - - /* Determine which features are supported */ - switch (version_info.version_mci) { - case MC_VERSION(1, 2): /* 310 */ - g_ctx.f_client_login = true; - /* Fall through */ - case MC_VERSION(1, 1): - g_ctx.f_multimap = true; - /* Fall through */ - case MC_VERSION(1, 0): /* 302 */ - g_ctx.f_mem_ext = true; - g_ctx.f_ta_auth = true; - /* Fall through */ - case MC_VERSION(0, 7): - g_ctx.f_timeout = true; - /* Fall through */ - case MC_VERSION(0, 6): /* 301 */ - break; - } - - ret = device_user_init(); - if (ret) - goto err_create_dev_user; - - return 0; - -err_create_dev_user: -err_version: -err_mcp_cmd: - mc_pm_stop(); -err_pm: - mc_scheduler_stop(); -err_sched: - mc_logging_stop(); -err_log: - mcp_stop(); -err_mcp: - return ret; -} - -static inline void mobicore_stop(void) -{ - mc_pm_stop(); - mc_scheduler_stop(); - mc_logging_stop(); - mcp_stop(); -} - -/* - * This function is called by the kernel during startup or by a insmod command. - * This device is installed and registered as cdev, then interrupt and - * queue handling is set up - */ -static int mobicore_init(void) -{ - int err = 0; - - dev_set_name(g_ctx.mcd, "TEE"); - - /* Do not remove or change the following trace. - * The string "MobiCore" is used to detect if Cannot continue! */ - if (!has_security_extensions()) { - MCDRV_ERROR("Hardware doesn't support ARM TrustZone!"); - return -ENODEV; - } - - /* Running in secure mode -> Cannot load the driver! */ - if (is_secure_mode()) { - MCDRV_ERROR("Running in secure MODE!"); - return -ENODEV; - } - - /* Init common API layer */ - api_init(); - - /* Init plenty of nice features */ - err = mc_fastcall_init(); - if (err) { - MCDRV_ERROR("Fastcall support init failed!"); - goto fail_fastcall_init; - } - - err = mcp_init(); - if (err) { - MCDRV_ERROR("MCP init failed!"); - goto fail_mcp_init; - } - - err = mc_logging_init(); - if (err) { - MCDRV_ERROR("Log init failed!"); - goto fail_log_init; - } - - /* The scheduler is the first to create a debugfs entry */ - g_ctx.debug_dir = debugfs_create_dir("trustonic_tee", NULL); - err = mc_scheduler_init(); - if (err) { - MCDRV_ERROR("Scheduler init failed!"); - goto fail_mc_device_sched_init; - } - - /* - * Create admin dev so that daemon can already communicate with - * the driver - */ - err = device_admin_init(mobicore_start); - if (err) - goto fail_creat_dev_admin; - - return 0; - -fail_creat_dev_admin: - mc_scheduler_exit(); -fail_mc_device_sched_init: - debugfs_remove(g_ctx.debug_dir); - mc_logging_exit(); -fail_log_init: - mcp_exit(); -fail_mcp_init: - mc_fastcall_exit(); -fail_fastcall_init: - return err; -} - -/* - * This function removes this device driver from the Linux device manager . - */ -static void mobicore_exit(void) -{ - MCDRV_DBG("enter"); - - devices_exit(); - mobicore_stop(); - mc_scheduler_exit(); - mc_logging_exit(); - mcp_exit(); - mc_fastcall_exit(); - debugfs_remove_recursive(g_ctx.debug_dir); - - MCDRV_DBG("exit"); -} - -/* Linux Driver Module Macros */ - -#ifdef MC_DEVICE_PROPNAME - -static int mobicore_probe(struct platform_device *pdev) -{ - g_ctx.mcd->of_node = pdev->dev.of_node; - mobicore_init(); - return 0; -} - -static const struct of_device_id of_match_table[] = { - { .compatible = MC_DEVICE_PROPNAME }, - { } -}; - -static struct platform_driver mc_plat_driver = { - .probe = mobicore_probe, - .driver = { - .name = "mcd", - .owner = THIS_MODULE, - .of_match_table = of_match_table, - } -}; - -static int mobicore_register(void) -{ - return platform_driver_register(&mc_plat_driver); -} - -static void mobicore_unregister(void) -{ - platform_driver_unregister(&mc_plat_driver); - mobicore_exit(); -} - -module_init(mobicore_register); -module_exit(mobicore_unregister); - -#else /* MC_DEVICE_PROPNAME */ - -module_init(mobicore_init); -module_exit(mobicore_exit); - -#endif /* !MC_DEVICE_PROPNAME */ - -MODULE_AUTHOR("Trustonic Limited"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MobiCore driver"); diff --git a/drivers/gud/MobiCoreDriver/main.h b/drivers/gud/MobiCoreDriver/main.h deleted file mode 100644 index cadc3d766147a..0000000000000 --- a/drivers/gud/MobiCoreDriver/main.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _MC_MAIN_H_ -#define _MC_MAIN_H_ - -#include /* gfp_t */ - -#define MC_VERSION(major, minor) \ - (((major & 0x0000ffff) << 16) | (minor & 0x0000ffff)) -#define MC_VERSION_MAJOR(x) ((x) >> 16) -#define MC_VERSION_MINOR(x) ((x) & 0xffff) - -/* MobiCore Driver Kernel Module context data. */ -struct mc_device_ctx { - struct device *mcd; - /* debugfs root */ - struct dentry *debug_dir; - - /* GP sessions waiting final close notif */ - struct list_head closing_sess; - struct mutex closing_lock; /* Closing sessions list */ - - /* Features */ - /* - SWd can set a time out to get scheduled at a future time */ - bool f_timeout; - /* - SWd supports memory extension which allows for bigger TAs */ - bool f_mem_ext; - /* - SWd supports TA authorisation */ - bool f_ta_auth; - /* - SWd can map several buffers at once */ - bool f_multimap; - /* - SWd supports GP client authentication */ - bool f_client_login; -}; - -extern struct mc_device_ctx g_ctx; - -struct kasnprintf_buf { - gfp_t gfp; - void *buf; - int size; - int off; -}; - -extern __printf(2, 3) -int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...); - -#endif /* _MC_MAIN_H_ */ diff --git a/drivers/gud/MobiCoreDriver/mci/mcifc.h b/drivers/gud/MobiCoreDriver/mci/mcifc.h deleted file mode 100644 index 4848c9e047fba..0000000000000 --- a/drivers/gud/MobiCoreDriver/mci/mcifc.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef MCIFC_H_ -#define MCIFC_H_ - -#include "platform.h" - -/** @name MobiCore FastCall Defines - * Defines for the two different FastCall's. - */ -/** @{ */ - -#include "platform.h" - -/* --- global ---- */ -#define MC_FC_INVALID ((uint32_t)0) /**< Invalid FastCall ID */ - -#if defined(CONFIG_ARM64) && !defined(MC_ARMV7_FC) - -/* These should be handled as 64-bit FCs; now they are more like 32bits... */ -#define MC_FC_STD64_BASE ((uint32_t)0xFF000000) -#define MC_FC_STD64(x) ((uint32_t)(MC_FC_STD64_BASE + (x))) - -#define MC_FC_INIT MC_FC_STD64(1) /**< Initializing FastCall. */ -#define MC_FC_INFO MC_FC_STD64(2) /**< Info FastCall. */ -#define MC_FC_MEM_TRACE MC_FC_STD64(10) /**< Enable SWd tracing via memory */ -#define MC_FC_SWAP_CPU MC_FC_STD64(54) /**< Change new active Core */ - -#else - -#define MC_FC_INIT ((uint32_t)(-1)) /**< Initializing FastCall. */ -#define MC_FC_INFO ((uint32_t)(-2)) /**< Info FastCall. */ -#define MC_FC_MEM_TRACE ((uint32_t)(-31)) /**< Enable SWd tracing via memory */ -#define MC_FC_SWAP_CPU ((uint32_t)(0x84000005)) /**< Change new active Core */ - -#endif - -/** @} */ - -/** @name MobiCore SMC Defines - * Defines the different secure monitor calls (SMC) for world switching. - * @{ */ -/**< Yield to switch from NWd to SWd. */ -#define MC_SMC_N_YIELD 3 -/**< SIQ to switch from NWd to SWd. */ -#define MC_SMC_N_SIQ 4 -/** @} */ - -/** @name MobiCore status - * MobiCore status information. - * @{ */ -/**< MobiCore is not yet initialized. FastCall FcInit() to set up MobiCore.*/ -#define MC_STATUS_NOT_INITIALIZED 0 -/**< Bad parameters have been passed in FcInit(). */ -#define MC_STATUS_BAD_INIT 1 -/**< MobiCore did initialize properly. */ -#define MC_STATUS_INITIALIZED 2 -/**< MobiCore kernel halted due to an unrecoverable exception. Further - * information is available extended info */ -#define MC_STATUS_HALT 3 -/** @} */ - -/** @name Extended Info Identifiers - * Extended info parameters for MC_FC_INFO to obtain further information depending on MobiCore state. - * @{ */ -/**< Version of the MobiCore Control Interface (MCI) */ -#define MC_EXT_INFO_ID_MCI_VERSION 0 -/**< MobiCore control flags */ -#define MC_EXT_INFO_ID_FLAGS 1 -/**< MobiCore halt condition code */ -#define MC_EXT_INFO_ID_HALT_CODE 2 -/**< MobiCore halt condition instruction pointer */ -#define MC_EXT_INFO_ID_HALT_IP 3 -/**< MobiCore fault counter */ -#define MC_EXT_INFO_ID_FAULT_CNT 4 -/**< MobiCore last fault cause */ -#define MC_EXT_INFO_ID_FAULT_CAUSE 5 -/**< MobiCore last fault meta */ -#define MC_EXT_INFO_ID_FAULT_META 6 -/**< MobiCore last fault threadid */ -#define MC_EXT_INFO_ID_FAULT_THREAD 7 -/**< MobiCore last fault instruction pointer */ -#define MC_EXT_INFO_ID_FAULT_IP 8 -/**< MobiCore last fault stack pointer */ -#define MC_EXT_INFO_ID_FAULT_SP 9 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_DFSR 10 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_ADFSR 11 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_DFAR 12 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_IFSR 13 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_AIFSR 14 -/**< MobiCore last fault ARM arch information */ -#define MC_EXT_INFO_ID_FAULT_ARCH_IFAR 15 -/**< MobiCore configured by Daemon via fc_init flag */ -#define MC_EXT_INFO_ID_MC_CONFIGURED 16 -/**< MobiCore scheduling status: idle/non-idle */ -#define MC_EXT_INFO_ID_MC_SCHED_STATUS 17 -/**< MobiCore runtime status: initialized, halted */ -#define MC_EXT_INFO_ID_MC_STATUS 18 -/**< MobiCore exception handler last partner */ -#define MC_EXT_INFO_ID_MC_EXC_PARTNER 19 -/**< MobiCore exception handler last peer */ -#define MC_EXT_INFO_ID_MC_EXC_IPCPEER 20 -/**< MobiCore exception handler last IPC message */ -#define MC_EXT_INFO_ID_MC_EXC_IPCMSG 21 -/**< MobiCore exception handler last IPC data */ -#define MC_EXT_INFO_ID_MC_EXC_IPCDATA 22 -/**< MobiCore exception handler last UUID (uses 4 slots: 23 to 26) */ -#define MC_EXT_INFO_ID_MC_EXC_UUID 23 -#define MC_EXT_INFO_ID_MC_EXC_UUID1 24 -#define MC_EXT_INFO_ID_MC_EXC_UUID2 25 -#define MC_EXT_INFO_ID_MC_EXC_UUID3 26 - -/** @} */ - -/** @name FastCall return values - * Return values of the MobiCore FastCalls. - * @{ */ -/**< No error. Everything worked fine. */ -#define MC_FC_RET_OK 0 -/**< FastCall was not successful. */ -#define MC_FC_RET_ERR_INVALID 1 -/**< MobiCore has already been initialized. */ -#define MC_FC_RET_ERR_ALREADY_INITIALIZED 5 -/** @} */ - -#endif /** MCIFC_H_ */ - -/** @} */ diff --git a/drivers/gud/MobiCoreDriver/mci/mcimcp.h b/drivers/gud/MobiCoreDriver/mci/mcimcp.h deleted file mode 100644 index 3eb2efea2c30c..0000000000000 --- a/drivers/gud/MobiCoreDriver/mci/mcimcp.h +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef MCP_H_ -#define MCP_H_ - -#include "mci/mcloadformat.h" - -/** Indicates a response */ -#define FLAG_RESPONSE BIT(31) - -/** Maximum number of buffers that can be mapped at once */ -#define MCP_MAP_MAX_BUF 4 - -/** MobiCore Return Code Defines. - * List of the possible MobiCore return codes. - */ -enum mcp_result { - /** Memory has successfully been mapped */ - MC_MCP_RET_OK = 0, - /** The session ID is invalid */ - MC_MCP_RET_ERR_INVALID_SESSION = 1, - /** The UUID of the Trustlet is unknown */ - MC_MCP_RET_ERR_UNKNOWN_UUID = 2, - /** The ID of the driver is unknown */ - MC_MCP_RET_ERR_UNKNOWN_DRIVER_ID = 3, - /** No more session are allowed */ - MC_MCP_RET_ERR_NO_MORE_SESSIONS = 4, - /** The container is invalid */ - MC_MCP_RET_ERR_CONTAINER_INVALID = 5, - /** The Trustlet is invalid */ - MC_MCP_RET_ERR_TRUSTLET_INVALID = 6, - /** The memory block has already been mapped before */ - MC_MCP_RET_ERR_ALREADY_MAPPED = 7, - /** Alignment or length error in the command parameters */ - MC_MCP_RET_ERR_INVALID_PARAM = 8, - /** No space left in the virtual address space of the session */ - MC_MCP_RET_ERR_OUT_OF_RESOURCES = 9, - /** WSM type unknown or broken WSM */ - MC_MCP_RET_ERR_INVALID_WSM = 10, - /** unknown error */ - MC_MCP_RET_ERR_UNKNOWN = 11, - /** Length of map invalid */ - MC_MCP_RET_ERR_INVALID_MAPPING_LENGTH = 12, - /** Map can only be applied to Trustlet session */ - MC_MCP_RET_ERR_MAPPING_TARGET = 13, - /** Couldn't open crypto session */ - MC_MCP_RET_ERR_OUT_OF_CRYPTO_RESOURCES = 14, - /** System Trustlet signature verification failed */ - MC_MCP_RET_ERR_SIGNATURE_VERIFICATION_FAILED = 15, - /** System Trustlet public key is wrong */ - MC_MCP_RET_ERR_WRONG_PUBLIC_KEY = 16, - /** Wrong containter type(s) */ - MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH = 17, - /** Container is locked (or not activated) */ - MC_MCP_RET_ERR_CONTAINER_LOCKED = 18, - /** SPID is not registered with root container */ - MC_MCP_RET_ERR_SP_NO_CHILD = 19, - /** UUID is not registered with sp container */ - MC_MCP_RET_ERR_TL_NO_CHILD = 20, - /** Unwrapping of root container failed */ - MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED = 21, - /** Unwrapping of service provider container failed */ - MC_MCP_RET_ERR_UNWRAP_SP_FAILED = 22, - /** Unwrapping of Trustlet container failed */ - MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED = 23, - /** Container version mismatch */ - MC_MCP_RET_ERR_CONTAINER_VERSION_MISMATCH = 24, - /** Decryption of service provider trustlet failed */ - MC_MCP_RET_ERR_SP_TL_DECRYPTION_FAILED = 25, - /** Hash check of service provider trustlet failed */ - MC_MCP_RET_ERR_SP_TL_HASH_CHECK_FAILED = 26, - /** Activation/starting of task failed */ - MC_MCP_RET_ERR_LAUNCH_TASK_FAILED = 27, - /** Closing of task not yet possible, try again later */ - MC_MCP_RET_ERR_CLOSE_TASK_FAILED = 28, - /**< Service is blocked and a session cannot be opened to it */ - MC_MCP_RET_ERR_SERVICE_BLOCKED = 29, - /**< Service is locked and a session cannot be opened to it */ - MC_MCP_RET_ERR_SERVICE_LOCKED = 30, - /**< Service was forcefully killed (due to an administrative command) */ - MC_MCP_RET_ERR_SERVICE_KILLED = 31, - /** The command is unknown */ - MC_MCP_RET_ERR_UNKNOWN_COMMAND = 50, - /** The command data is invalid */ - MC_MCP_RET_ERR_INVALID_DATA = 51 -}; - -/** Possible MCP Command IDs - * Command ID must be between 0 and 0x7FFFFFFF. - */ -enum cmd_id { - /** Invalid command ID */ - MC_MCP_CMD_ID_INVALID = 0x00, - /** Open a session */ - MC_MCP_CMD_OPEN_SESSION = 0x01, - /** Close an existing session */ - MC_MCP_CMD_CLOSE_SESSION = 0x03, - /** Map WSM to session */ - MC_MCP_CMD_MAP = 0x04, - /** Unmap WSM from session */ - MC_MCP_CMD_UNMAP = 0x05, - /** Prepare for suspend */ - MC_MCP_CMD_SUSPEND = 0x06, - /** Resume from suspension */ - MC_MCP_CMD_RESUME = 0x07, - /** Get MobiCore version information */ - MC_MCP_CMD_GET_MOBICORE_VERSION = 0x09, - /** Close MCP and unmap MCI */ - MC_MCP_CMD_CLOSE_MCP = 0x0A, - /** Load token for device attestation */ - MC_MCP_CMD_LOAD_TOKEN = 0x0B, - /** Check that TA can be loaded */ - MC_MCP_CMD_CHECK_LOAD_TA = 0x0C, - /** Map multiple WSMs to session */ - MC_MCP_CMD_MULTIMAP = 0x0D, - /** Unmap multiple WSMs to session */ - MC_MCP_CMD_MULTIUNMAP = 0x0E, -}; - -/* - * Types of WSM known to the MobiCore. - */ -#define WSM_TYPE_MASK 0xFF -#define WSM_INVALID 0 /** Invalid memory type */ -#define WSM_L2 2 /** Buffer mapping uses L2/L3 table */ -#define WSM_L1 3 /** Buffer mapping uses fake L1 table */ - -/** Magic number used to identify if Open Command supports GP client - * authentication. - */ -#define MC_GP_CLIENT_AUTH_MAGIC 0x47504131 /* "GPA1" */ - -/** Command header. - * It just contains the command ID. Only values specified in cmd_id are - * allowed as command IDs. If the command ID is unspecified the MobiCore - * returns an empty response with the result set to - * MC_MCP_RET_ERR_UNKNOWN_COMMAND. - */ -struct cmd_header { - enum cmd_id cmd_id; /** Command ID of the command */ -}; - -/** Response header. - * MobiCore will reply to every MCP command with an MCP response. Like the MCP - * command the response consists of a header followed by response data. The - * response is written to the same memory location as the MCP command. - */ -struct rsp_header { - uint32_t rsp_id; /** Command ID | FLAG_RESPONSE */ - enum mcp_result result; /** Result of the command execution */ -}; - -/** @defgroup CMD MCP Commands - */ - -/** @defgroup ASMCMD Administrative Commands - */ - -/** @defgroup MCPGETMOBICOREVERSION GET_MOBICORE_VERSION - * Get MobiCore version info. - * - */ - -/** Get MobiCore Version Command */ -struct cmd_get_version { - struct cmd_header cmd_header; /** Command header */ -}; - -/** Get MobiCore Version Command Response */ -struct rsp_get_version { - struct rsp_header rsp_header; /** Response header */ - struct mc_version_info version_info; /** MobiCore version info */ -}; - -/** @defgroup POWERCMD Power Management Commands - */ - -/** @defgroup MCPSUSPEND SUSPEND - * Prepare MobiCore suspension. - * This command allows MobiCore and MobiCore drivers to release or clean - * resources and save device state. - * - */ - -/** Suspend Command */ -struct cmd_suspend { - struct cmd_header cmd_header; /** Command header */ -}; - -/** Suspend Command Response */ -struct rsp_suspend { - struct rsp_header rsp_header; /** Response header */ -}; - -/** @defgroup MCPRESUME RESUME - * Resume MobiCore from suspension. - * This command allows MobiCore and MobiCore drivers to reinitialize hardware - * affected by suspension. - * - */ - -/** Resume Command */ -struct cmd_resume { - struct cmd_header cmd_header; /** Command header */ -}; - -/** Resume Command Response */ -struct rsp_resume { - struct rsp_header rsp_header; /** Response header */ -}; - -/** @defgroup SESSCMD Session Management Commands - */ - -/** @defgroup MCPOPEN OPEN - * Load and open a session to a Trustlet. - * The OPEN command loads Trustlet data to the MobiCore context and opens a - * session to the Trustlet. If wsm_data_type is WSM_INVALID MobiCore tries to - * start a pre-installed Trustlet associated with the uuid passed. The uuid - * passed must match the uuid contained in the load data (if available). - * On success, MobiCore returns the session ID which can be used for further - * communication. - */ - -/** GP client authentication data */ -struct cmd_open_data { - uint32_t mclf_magic; /** ASCII "MCLF" on older versions */ - struct identity identity; /** Login method and data */ -}; - -/** Open Command */ -struct cmd_open { - struct cmd_header cmd_header; /** Command header */ - struct mc_uuid_t uuid; /** Service UUID */ - uint8_t unused[4]; /** Padding to be 64-bit aligned */ - uint64_t adr_tci_buffer; /** Physical address of the TCI MMU */ - uint64_t adr_load_data; /** Physical address of the data MMU */ - uint32_t ofs_tci_buffer; /** Offset to the data */ - uint32_t len_tci_buffer; /** Length of the TCI */ - uint32_t wsmtype_tci; /** Type of WSM used for the TCI */ - uint32_t wsm_data_type; /** Type of MMU */ - uint32_t ofs_load_data; /** Offset to the data */ - uint32_t len_load_data; /** Length of the data to load */ - union { - struct cmd_open_data cmd_open_data; /** Client login data */ - union mclf_header tl_header; /** Service header */ - }; - uint32_t is_gpta; /** true if looking for an SD/GP-TA */ -}; - -/** Open Command Response */ -struct rsp_open { - struct rsp_header rsp_header; /** Response header */ - uint32_t session_id; /** Session ID */ -}; - -/** TA Load Check Command */ -struct cmd_check_load { - struct cmd_header cmd_header; /** Command header */ - struct mc_uuid_t uuid; /** Service UUID */ - uint64_t adr_load_data; /** Physical address of the data */ - uint32_t wsm_data_type; /** Type of MMU */ - uint32_t ofs_load_data; /** Offset to the data */ - uint32_t len_load_data; /** Length of the data to load */ - union mclf_header tl_header; /** Service header */ -}; - -/** TA Load Check Response */ -struct rsp_check_load { - struct rsp_header rsp_header; /** Response header */ -}; - -/** @defgroup MCPCLOSE CLOSE - * Close an existing session to a Trustlet. - * The CLOSE command terminates a session and frees all resources in the - * MobiCore system which are currently occupied by the session. Before closing - * the session, the MobiCore runtime management waits until all pending - * operations, like calls to drivers, invoked by the Trustlet have been - * terminated. Mapped memory will automatically be unmapped from the MobiCore - * context. The NWd is responsible for processing the freed memory according to - * the Rich-OS needs. - * - */ - -/** Close Command */ -struct cmd_close { - struct cmd_header cmd_header; /** Command header */ - uint32_t session_id; /** Session ID */ -}; - -/** Close Command Response */ -struct rsp_close { - struct rsp_header rsp_header; /** Response header */ -}; - -/** @defgroup MCPMAP MAP - * Map a portion of memory to a session. - * The MAP command provides a block of memory to the context of a service. - * The memory then becomes world-shared memory (WSM). - * The only allowed memory type here is WSM_L2. - */ - -/** Map Command */ -struct cmd_map { - struct cmd_header cmd_header; /** Command header */ - uint32_t session_id; /** Session ID */ - uint32_t wsm_type; /** Type of MMU */ - uint32_t ofs_buffer; /** Offset to the payload */ - uint64_t adr_buffer; /** Physical address of the MMU */ - uint32_t len_buffer; /** Length of the buffer */ -}; - -#define MCP_MAP_MAX 0x100000 /** Maximum length for MCP map */ - -/** Map Command Response */ -struct rsp_map { - struct rsp_header rsp_header; /** Response header */ - /** Virtual address the WSM is mapped to, may include an offset! */ - uint32_t secure_va; -}; - -/** @defgroup MCPUNMAP UNMAP - * Unmap a portion of world-shared memory from a session. - * The UNMAP command is used to unmap a previously mapped block of - * world shared memory from the context of a session. - * - * Attention: The memory block will be immediately unmapped from the specified - * session. If the service is still accessing the memory, the service will - * trigger a segmentation fault. - */ - -/** Unmap Command */ -struct cmd_unmap { - struct cmd_header cmd_header; /** Command header */ - uint32_t session_id; /** Session ID */ - uint32_t wsm_type; /** Type of WSM used of the memory */ - /** Virtual address the WSM is mapped to, may include an offset! */ - uint32_t secure_va; - uint32_t virtual_buffer_len; /** Length of virtual buffer */ -}; - -/** Unmap Command Response */ -struct rsp_unmap { - struct rsp_header rsp_header; /** Response header */ -}; - -/** @defgroup MCPLOADTOKEN - * Load a token from the normal world and share it with type of - * function. elementCnt must be a power of two and the power needs - * to be smaller than power of uint32_t (obviously 32). - */ -struct notification_queue { - struct notification_queue_header hdr; /** Queue header */ - struct notification notification[MIN_NQ_ELEM]; /** Elements */ -}; - -#endif /** NQ_H_ */ diff --git a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h b/drivers/gud/MobiCoreDriver/mci/mcloadformat.h deleted file mode 100644 index f12f618bb0dc6..0000000000000 --- a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef MCLOADFORMAT_H_ -#define MCLOADFORMAT_H_ - -/** Trustlet Blob length info */ -#define MC_TLBLOBLEN_MAGIC 0x7672746C /* Magic for SWd: vrtl */ -#define MAX_SO_CONT_SIZE 512 /* Max size for a container */ - -/** MCLF flags */ -/**< Loaded service cannot be unloaded from MobiCore. */ -#define MC_SERVICE_HEADER_FLAGS_PERMANENT BIT(0) -/**< Service has no WSM control interface. */ -#define MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE BIT(1) -/**< Service can be debugged. */ -#define MC_SERVICE_HEADER_FLAGS_DEBUGGABLE BIT(2) -/**< New-layout trusted application or trusted driver. */ -#define MC_SERVICE_HEADER_FLAGS_EXTENDED_LAYOUT BIT(3) - -/** Service type. - * The service type defines the type of executable. - */ -enum service_type { - SERVICE_TYPE_ILLEGAL = 0, - SERVICE_TYPE_DRIVER = 1, - SERVICE_TYPE_SP_TRUSTLET = 2, - SERVICE_TYPE_SYSTEM_TRUSTLET = 3, - SERVICE_TYPE_MIDDLEWARE = 4, - SERVICE_TYPE_LAST_ENTRY = 5, -}; - -/** - * Descriptor for a memory segment. - */ -struct segment_descriptor { - uint32_t start; /**< Virtual start address */ - uint32_t len; /**< Segment length in bytes */ -}; - -/** - * MCLF intro for data structure identification. - * Must be the first element of a valid MCLF file. - */ -struct mclf_intro { - uint32_t magic; /**< Header magic value ASCII "MCLF" */ - uint32_t version; /**< Version the MCLF header struct */ -}; - -/** - * @defgroup MCLF_VER_V2 MCLF Version 32 - * @ingroup MCLF_VER - * - * @addtogroup MCLF_VER_V2 - */ - -/* - * GP TA identity. - */ -struct identity { - /**< GP TA login type */ - uint32_t login_type; - /**< GP TA login data */ - uint8_t login_data[16]; -}; - -/** - * Version 2.1/2.2 MCLF header. - */ -struct mclf_header_v2 { - /**< MCLF header start with the mandatory intro */ - struct mclf_intro intro; - /**< Service flags */ - uint32_t flags; - /**< Type of memory the service must be executed from */ - uint32_t mem_type; - /**< Type of service */ - enum service_type service_type; - /**< Number of instances which can be run simultaneously */ - uint32_t num_instances; - /**< Loadable service unique identifier (UUID) */ - struct mc_uuid_t uuid; - /**< If the service_type is SERVICE_TYPE_DRIVER the Driver ID is used */ - uint32_t driver_id; - /**< - * Number of threads (N) in a service: - * SERVICE_TYPE_SP_TRUSTLET: N = 1 - * SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1 - * SERVICE_TYPE_DRIVER: N >= 1 - */ - uint32_t num_threads; - /**< Virtual text segment */ - struct segment_descriptor text; - /**< Virtual data segment */ - struct segment_descriptor data; - /**< Length of the BSS segment in bytes. MUST be at least 8 byte */ - uint32_t bss_len; - /**< Virtual start address of service code */ - uint32_t entry; - /**< Version of the interface the driver exports */ - uint32_t service_version; -}; - -/** - * @addtogroup MCLF - */ - -/** MCLF header */ -union mclf_header { - /**< Intro for data identification */ - struct mclf_intro intro; - /**< Version 2 header */ - struct mclf_header_v2 mclf_header_v2; -}; - -struct mc_blob_len_info { - uint32_t magic; /**< New blob format magic number */ - uint32_t root_size; /**< Root container size */ - uint32_t sp_size; /**< SP container size */ - uint32_t ta_size; /**< TA container size */ - uint32_t reserved[4]; /**< Reserved for further Use */ -}; - -#endif /* MCLOADFORMAT_H_ */ diff --git a/drivers/gud/MobiCoreDriver/mcp.c b/drivers/gud/MobiCoreDriver/mcp.c deleted file mode 100644 index 693fd42e2d4b5..0000000000000 --- a/drivers/gud/MobiCoreDriver/mcp.c +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_admin.h" - -#include "mci/mcimcp.h" -#include "mci/mcifc.h" -#include "mci/mcinq.h" /* SID_MCP */ - -#include "platform.h" /* IRQ number */ -#include "fastcall.h" -#include "debug.h" -#include "logging.h" -#include "mcp.h" - -/* respond timeout for MCP notification, in secs */ -#define MCP_TIMEOUT 10 -#define MCP_RETRIES 5 -#define MCP_NF_QUEUE_SZ 8 -#define NQ_NUM_ELEMS 16 - -static void mc_irq_worker(struct work_struct *data); -DECLARE_WORK(irq_work, mc_irq_worker); - -static const struct { - unsigned int index; - const char *msg; -} status_map[] = { - /**< MobiCore control flags */ - { MC_EXT_INFO_ID_FLAGS, "flags"}, - /**< MobiCore halt condition code */ - { MC_EXT_INFO_ID_HALT_CODE, "haltCode"}, - /**< MobiCore halt condition instruction pointer */ - { MC_EXT_INFO_ID_HALT_IP, "haltIp"}, - /**< MobiCore fault counter */ - { MC_EXT_INFO_ID_FAULT_CNT, "faultRec.cnt"}, - /**< MobiCore last fault cause */ - { MC_EXT_INFO_ID_FAULT_CAUSE, "faultRec.cause"}, - /**< MobiCore last fault meta */ - { MC_EXT_INFO_ID_FAULT_META, "faultRec.meta"}, - /**< MobiCore last fault threadid */ - { MC_EXT_INFO_ID_FAULT_THREAD, "faultRec.thread"}, - /**< MobiCore last fault instruction pointer */ - { MC_EXT_INFO_ID_FAULT_IP, "faultRec.ip"}, - /**< MobiCore last fault stack pointer */ - { MC_EXT_INFO_ID_FAULT_SP, "faultRec.sp"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_DFSR, "faultRec.arch.dfsr"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_ADFSR, "faultRec.arch.adfsr"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_DFAR, "faultRec.arch.dfar"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_IFSR, "faultRec.arch.ifsr"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_AIFSR, "faultRec.arch.aifsr"}, - /**< MobiCore last fault ARM arch information */ - { MC_EXT_INFO_ID_FAULT_ARCH_IFAR, "faultRec.arch.ifar"}, - /**< MobiCore configured by Daemon via fc_init flag */ - { MC_EXT_INFO_ID_MC_CONFIGURED, "mcData.flags"}, - /**< MobiCore exception handler last partner */ - { MC_EXT_INFO_ID_MC_EXC_PARTNER, "mcExcep.partner"}, - /**< MobiCore exception handler last peer */ - { MC_EXT_INFO_ID_MC_EXC_IPCPEER, "mcExcep.peer"}, - /**< MobiCore exception handler last IPC message */ - { MC_EXT_INFO_ID_MC_EXC_IPCMSG, "mcExcep.cause"}, - /**< MobiCore exception handler last IPC data */ - {MC_EXT_INFO_ID_MC_EXC_IPCDATA, "mcExcep.meta"}, -}; - -static struct mcp_context { - struct mutex buffer_lock; /* Lock on SWd communication buffer */ - struct mutex queue_lock; /* Lock for MCP messages */ - struct mcp_buffer *mcp_buffer; - struct tbase_session *session; - struct completion complete; - bool mcp_dead; - int irq; - int (*scheduler_cb)(enum mcp_scheduler_commands); - void (*crashhandler_cb)(void); - /* MobiCore MCI information */ - unsigned int order; - union { - void *base; - struct { - struct notification_queue *tx; - struct notification_queue *rx; - } nq; - }; - /* - * This notifications list is to be used to queue notifications when the - * notification queue overflows, so no session gets its notification - * lost, especially MCP. - */ - struct mutex notifications_mutex; - struct list_head notifications; - struct mcp_session mcp_session; /* Pseudo session for MCP */ - /* Unexpected notification (during MCP open) */ - struct mutex unexp_notif_mutex; - struct notification unexp_notif; - /* Sessions */ - struct mutex sessions_lock; - struct list_head sessions; - /* Dump buffer */ - struct kasnprintf_buf dump; -} mcp_ctx; - -static inline void mark_mcp_dead(void) -{ - mcp_ctx.mcp_dead = true; - complete(&mcp_ctx.complete); -} - -static inline int mcp_set_sleep_mode_rq(uint16_t sleep_req) -{ - mutex_lock(&mcp_ctx.buffer_lock); - mcp_ctx.mcp_buffer->mc_flags.sleep_mode.sleep_req = sleep_req; - mutex_unlock(&mcp_ctx.buffer_lock); - return 0; -} - -static ssize_t debug_crashdump_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - if (mcp_ctx.dump.off) - return simple_read_from_buffer(user_buf, count, ppos, - mcp_ctx.dump.buf, - mcp_ctx.dump.off); - - return 0; -} - -static const struct file_operations mc_debug_crashdump_ops = { - .read = debug_crashdump_read, - .llseek = default_llseek, -}; - -static void mcp_dump_mobicore_status(void) -{ - char uuid_str[33]; - int ret = 0; - int i; - - if (mcp_ctx.dump.off) - ret = -EBUSY; - - /* read additional info about exception-point and print */ - dev_err(g_ctx.mcd, "= 0) - ret = kasnprintf(&mcp_ctx.dump, - "%-20s= 0x%08x\n", - status_map[i].msg, info); - } - } - - /* construct UUID string */ - for (i = 0; i < 4; i++) { - uint32_t info; - int j; - - if (mc_fc_info(MC_EXT_INFO_ID_MC_EXC_UUID + i, NULL, &info)) - return; - - for (j = 0; j < sizeof(info); j++) { - snprintf(&uuid_str[(i * sizeof(info) + j) * 2], 3, - "%02x", (info >> (j * 8)) & 0xff); - } - } - - dev_err(g_ctx.mcd, " %-20s= 0x%s\n", "mcExcep.uuid", uuid_str); - if (ret >= 0) - ret = kasnprintf(&mcp_ctx.dump, "%-20s= 0x%s\n", "mcExcep.uuid", - uuid_str); - - if (ret < 0) { - kfree(mcp_ctx.dump.buf); - mcp_ctx.dump.off = 0; - return; - } - - debugfs_create_file("crashdump", 0400, g_ctx.debug_dir, NULL, - &mc_debug_crashdump_ops); - if (mcp_ctx.crashhandler_cb) - mcp_ctx.crashhandler_cb(); -} - -void mcp_session_init(struct mcp_session *session, bool is_gp, - const struct identity *identity) -{ - /* close_work is initialized by the caller */ - INIT_LIST_HEAD(&session->list); - INIT_LIST_HEAD(&session->notifications_list); - mutex_init(&session->notif_wait_lock); - init_completion(&session->completion); - mutex_init(&session->exit_code_lock); - session->state = MCP_SESSION_RUNNING; - session->is_gp = is_gp; - if (is_gp) - session->identity = *identity; -} - -static inline bool mcp_session_isrunning(struct mcp_session *session) -{ - bool ret; - - mutex_lock(&mcp_ctx.sessions_lock); - ret = session->state == MCP_SESSION_RUNNING; - mutex_unlock(&mcp_ctx.sessions_lock); - return ret; -} - -/* - * session remains valid thanks to the upper layers reference counters, but the - * SWd session may have died, in which case we are informed. - */ -int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout) -{ - int ret = 0; - - mutex_lock(&session->notif_wait_lock); - if (!mcp_session_isrunning(session)) { - ret = -ENXIO; - goto end; - } - - if (mcp_session_exitcode(session)) { - ret = -ECOMM; - goto end; - } - - if (timeout < 0) { - ret = wait_for_completion_interruptible(&session->completion); - if (ret) - goto end; - } else { - ret = wait_for_completion_interruptible_timeout( - &session->completion, timeout * HZ / 1000); - if (ret < 0) - /* Interrupted */ - goto end; - - if (!ret) { - /* Timed out */ - ret = -ETIME; - goto end; - } - - ret = 0; - } - - if (mcp_session_exitcode(session)) { - ret = -ECOMM; - goto end; - } - - if (!mcp_session_isrunning(session)) { - ret = -ENXIO; - goto end; - } - -end: - mutex_unlock(&session->notif_wait_lock); - if (ret) - dev_info(g_ctx.mcd, "%s session %x ec %d ret %d\n", __func__, - session->id, session->exit_code, ret); - - return ret; -} - -int32_t mcp_session_exitcode(struct mcp_session *session) -{ - int32_t exit_code; - - mutex_lock(&session->exit_code_lock); - exit_code = session->exit_code; - mutex_unlock(&session->exit_code_lock); - if (exit_code) - dev_info(g_ctx.mcd, "%s session %x ec %d\n", __func__, - session->id, exit_code); - - return exit_code; -} - -int mcp_suspend(void) -{ - return mcp_set_sleep_mode_rq(MC_FLAG_REQ_TO_SLEEP); -} - -int mcp_resume(void) -{ - return mcp_set_sleep_mode_rq(MC_FLAG_NO_SLEEP_REQ); -} - -bool mcp_suspended(void) -{ - struct mcp_flags *flags = &mcp_ctx.mcp_buffer->mc_flags; - bool ret; - - mutex_lock(&mcp_ctx.buffer_lock); - ret = flags->sleep_mode.ready_to_sleep & MC_STATE_READY_TO_SLEEP; - if (!ret) { - MCDRV_DBG("IDLE=%d!", flags->schedule); - MCDRV_DBG("Request Sleep=%d!", flags->sleep_mode.sleep_req); - MCDRV_DBG("Sleep Ready=%d!", flags->sleep_mode.ready_to_sleep); - } - - mutex_unlock(&mcp_ctx.buffer_lock); - return ret; -} - -bool mcp_get_idle_timeout(int32_t *timeout) -{ - uint32_t schedule; - bool ret; - - mutex_lock(&mcp_ctx.buffer_lock); - schedule = mcp_ctx.mcp_buffer->mc_flags.schedule; - if (schedule == MC_FLAG_SCHEDULE_IDLE) { - if (g_ctx.f_timeout) - *timeout = mcp_ctx.mcp_buffer->mc_flags.timeout_ms; - else - *timeout = -1; - - ret = true; - } else { - ret = false; - } - - mutex_unlock(&mcp_ctx.buffer_lock); - return ret; -} - -void mcp_reset_idle_timeout(void) -{ - mutex_lock(&mcp_ctx.buffer_lock); - mcp_ctx.mcp_buffer->mc_flags.timeout_ms = -1; - mutex_unlock(&mcp_ctx.buffer_lock); -} - -static inline int wait_mcp_notification(void) -{ - unsigned long timeout = msecs_to_jiffies(MCP_TIMEOUT * 1000); - int try; - - /* - * Total timeout is MCP_TIMEOUT * MCP_RETRIES, but we check for a crash - * to try and terminate before then if things go wrong. - */ - for (try = 1; try <= MCP_RETRIES; try++) { - uint32_t status; - int ret; - - /* - * Wait non-interruptible to keep MCP synchronised even if caller - * is interrupted by signal. - */ - ret = wait_for_completion_timeout(&mcp_ctx.complete, timeout); - if (ret > 0) - return 0; - - MCDRV_ERROR("No answer after %ds", MCP_TIMEOUT * try); - - /* If SWd halted, exit now */ - if (!mc_fc_info(MC_EXT_INFO_ID_MCI_VERSION, &status, NULL) && - (status == MC_STATUS_HALT)) - break; - } - - /* mcp_message; - enum cmd_id cmd_id = cmd->cmd_header.cmd_id; - - mutex_lock(&mcp_ctx.queue_lock); - if (mcp_ctx.mcp_dead) - goto out; - - /* Copy message to MCP buffer */ - memcpy(msg, cmd, sizeof(*msg)); - - /* Poke tbase */ - err = mcp_notify(&mcp_ctx.mcp_session); - if (!err) - err = wait_mcp_notification(); - - if (err) - goto out; - - /* Check response ID */ - if (msg->rsp_header.rsp_id != (cmd_id | FLAG_RESPONSE)) { - MCDRV_ERROR("MCP command got invalid response (0x%X)", - msg->rsp_header.rsp_id); - err = -EBADE; - goto out; - } - - /* Convert result */ - switch (msg->rsp_header.result) { - case MC_MCP_RET_OK: - err = 0; - break; - case MC_MCP_RET_ERR_CLOSE_TASK_FAILED: - case MC_MCP_RET_ERR_NO_MORE_SESSIONS: - err = -EBUSY; - break; - case MC_MCP_RET_ERR_OUT_OF_RESOURCES: - err = -ENOSPC; - break; - case MC_MCP_RET_ERR_UNKNOWN_UUID: - err = -ENOENT; - break; - case MC_MCP_RET_ERR_WRONG_PUBLIC_KEY: - err = -EKEYREJECTED; - break; - case MC_MCP_RET_ERR_SERVICE_BLOCKED: - err = -ECONNREFUSED; - break; - case MC_MCP_RET_ERR_SERVICE_LOCKED: - err = -ECONNABORTED; - break; - case MC_MCP_RET_ERR_SERVICE_KILLED: - err = -ECONNRESET; - break; - default: - MCDRV_ERROR("cmd %d returned %d.", cmd_id, - msg->rsp_header.result); - err = -EPERM; - goto out; - } - - /* Copy response back to caller struct */ - memcpy(cmd, msg, sizeof(*cmd)); - -out: - mutex_unlock(&mcp_ctx.queue_lock); - return err; -} - -int mcp_get_version(struct mc_version_info *version_info) -{ - union mcp_message cmd; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_GET_MOBICORE_VERSION; - ret = mcp_cmd(&cmd); - if (!ret) - memcpy(version_info, &cmd.rsp_get_version.version_info, - sizeof(*version_info)); - - return ret; -} - -int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *map) -{ - union mcp_message cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_LOAD_TOKEN; - cmd.cmd_load_token.wsm_data_type = map->type; - cmd.cmd_load_token.adr_load_data = map->phys_addr; - cmd.cmd_load_token.ofs_load_data = map->offset; - cmd.cmd_load_token.len_load_data = map->length; - return mcp_cmd(&cmd); -} - -int mcp_load_check(const struct tbase_object *obj, - const struct mcp_buffer_map *map) -{ - const union mclf_header *header; - union mcp_message cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_CHECK_LOAD_TA; - /* Data */ - cmd.cmd_check_load.wsm_data_type = map->type; - cmd.cmd_check_load.adr_load_data = map->phys_addr; - cmd.cmd_check_load.ofs_load_data = map->offset; - cmd.cmd_check_load.len_load_data = map->length; - /* Header */ - header = (union mclf_header *)(obj->data + obj->header_length); - cmd.cmd_check_load.uuid = header->mclf_header_v2.uuid; - return mcp_cmd(&cmd); -} - -int mcp_open_session(struct mcp_session *session, - const struct tbase_object *obj, - const struct mcp_buffer_map *map, - const struct mcp_buffer_map *tci_map) -{ - static DEFINE_MUTEX(local_mutex); - const union mclf_header *header; - union mcp_message cmd; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_OPEN_SESSION; - /* Data */ - cmd.cmd_open.wsm_data_type = map->type; - cmd.cmd_open.adr_load_data = map->phys_addr; - cmd.cmd_open.ofs_load_data = map->offset; - cmd.cmd_open.len_load_data = map->length; - /* Buffer */ - if (tci_map) { - cmd.cmd_open.wsmtype_tci = tci_map->type; - cmd.cmd_open.adr_tci_buffer = tci_map->phys_addr; - cmd.cmd_open.ofs_tci_buffer = tci_map->offset; - cmd.cmd_open.len_tci_buffer = tci_map->length; - } else { - cmd.cmd_open.wsmtype_tci = WSM_INVALID; - } - /* Header */ - header = (union mclf_header *)(obj->data + obj->header_length); - cmd.cmd_open.uuid = header->mclf_header_v2.uuid; - cmd.cmd_open.is_gpta = session->is_gp; - /* Reset unexpected notification */ - mutex_lock(&local_mutex); - mcp_ctx.unexp_notif.session_id = SID_MCP; /* Cannot be */ - if (!g_ctx.f_client_login) { - memcpy(&cmd.cmd_open.tl_header, header, - sizeof(cmd.cmd_open.tl_header)); - } else { - cmd.cmd_open.cmd_open_data.mclf_magic = MC_GP_CLIENT_AUTH_MAGIC; - if (session->is_gp) - cmd.cmd_open.cmd_open_data.identity = session->identity; - } - - /* Send MCP open command */ - ret = mcp_cmd(&cmd); - if (!ret) { - session->id = cmd.rsp_open.session_id; - /* Add to list of sessions */ - mutex_lock(&mcp_ctx.sessions_lock); - list_add(&session->list, &mcp_ctx.sessions); - mutex_unlock(&mcp_ctx.sessions_lock); - /* Check for spurious notification */ - mutex_lock(&mcp_ctx.unexp_notif_mutex); - if (mcp_ctx.unexp_notif.session_id == session->id) { - mutex_lock(&session->exit_code_lock); - session->exit_code = mcp_ctx.unexp_notif.payload; - mutex_unlock(&session->exit_code_lock); - complete(&session->completion); - } - - mutex_unlock(&mcp_ctx.unexp_notif_mutex); - } - - mutex_unlock(&local_mutex); - return ret; -} - -/* - * Legacy and GP TAs close differently: - * - GP TAs always send a notification with payload, whether on close or crash - * - Legacy TAs only send a notification with payload on crash - * - GP TAs may take time to close, and we get -EBUSY back from mcp_cmd - * - Legacy TAs always close when asked, unless they are driver in which case - * they just don't close at all - */ -int mcp_close_session(struct mcp_session *session) -{ - union mcp_message cmd; - int ret; - - /* state is either MCP_SESSION_RUNNING or MCP_SESSION_CLOSING_GP */ - mutex_lock(&mcp_ctx.sessions_lock); - if (session->state == MCP_SESSION_RUNNING) - session->state = MCP_SESSION_CLOSE_PREPARE; - - mutex_unlock(&mcp_ctx.sessions_lock); - /* Signal an eventual waiter that SWd session is going away */ - complete(&session->completion); - /* Send MCP command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_SESSION; - cmd.cmd_close.session_id = session->id; - ret = mcp_cmd(&cmd); - mutex_lock(&mcp_ctx.sessions_lock); - /* - * The GP TA may already have sent its exit code, in which case the - * state has also been changed to MCP_SESSION_CLOSE_NOTIFIED. - */ - if (!ret) { - session->state = MCP_SESSION_CLOSED; - list_del(&session->list); - mutex_lock(&mcp_ctx.notifications_mutex); - list_del(&session->notifications_list); - mutex_unlock(&mcp_ctx.notifications_mutex); - } else if (ret == -EBUSY) { - if (session->state == MCP_SESSION_CLOSE_NOTIFIED) - /* GP TA already closed */ - schedule_work(&session->close_work); - - session->state = MCP_SESSION_CLOSING_GP; - } else { - /* Something is not right, assume session is still running */ - session->state = MCP_SESSION_RUNNING; - } - - mutex_unlock(&mcp_ctx.sessions_lock); - return ret; -} - -int mcp_map(uint32_t session_id, struct mcp_buffer_map *map) -{ - union mcp_message cmd; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_MAP; - cmd.cmd_map.session_id = session_id; - cmd.cmd_map.wsm_type = map->type; - cmd.cmd_map.adr_buffer = map->phys_addr; - cmd.cmd_map.ofs_buffer = map->offset; - cmd.cmd_map.len_buffer = map->length; - ret = mcp_cmd(&cmd); - if (!ret) - map->secure_va = cmd.rsp_map.secure_va; - - return ret; -} - -int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *map) -{ - union mcp_message cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_UNMAP; - cmd.cmd_unmap.session_id = session_id; - cmd.cmd_unmap.wsm_type = map->type; - cmd.cmd_unmap.virtual_buffer_len = map->length; - cmd.cmd_unmap.secure_va = map->secure_va; - return mcp_cmd(&cmd); -} - -int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *maps) -{ - struct mcp_buffer_map *map = maps; - union mcp_message cmd; - struct buffer_map *buf = cmd.cmd_multimap.bufs; - int ret = 0; - uint32_t i; - - /* Prepare command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIMAP; - cmd.cmd_multimap.session_id = session_id; - for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) { - buf->wsm_type = map->type; - buf->adr_buffer = map->phys_addr; - buf->ofs_buffer = map->offset; - buf->len_buffer = map->length; - } - - ret = mcp_cmd(&cmd); - if (ret) - return ret; - - /* Return secure virtual addresses */ - map = maps; - for (i = 0; i < MC_MAP_MAX; i++, map++) - map->secure_va = cmd.rsp_multimap.secure_va[i]; - - return 0; -} - -int mcp_multiunmap(uint32_t session_id, const struct mcp_buffer_map *maps) -{ - const struct mcp_buffer_map *map = maps; - union mcp_message cmd; - struct buffer_unmap *buf = cmd.cmd_multiunmap.bufs; - uint32_t i; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIUNMAP; - cmd.cmd_multiunmap.session_id = session_id; - for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) { - buf->secure_va = map->secure_va; - buf->len_buffer = map->length; - } - - return mcp_cmd(&cmd); -} - -static int mcp_close(void) -{ - union mcp_message cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_MCP; - return mcp_cmd(&cmd); -} - -static inline bool notif_queue_full(void) -{ - struct notification_queue *tx = mcp_ctx.nq.tx; - - return (tx->hdr.write_cnt - tx->hdr.read_cnt) == tx->hdr.queue_size; -} - -static inline void notif_queue_push(uint32_t session_id) -{ - struct notification_queue_header *hdr = &mcp_ctx.nq.tx->hdr; - uint32_t i = hdr->write_cnt % hdr->queue_size; - - mcp_ctx.nq.tx->notification[i].session_id = session_id; - mcp_ctx.nq.tx->notification[i].payload = 0; - hdr->write_cnt++; -} - -static inline bool mcp_notifications_flush_nolock(void) -{ - bool flushed = false; - - while (!list_empty(&mcp_ctx.notifications) && !notif_queue_full()) { - struct mcp_session *session; - - session = list_first_entry(&mcp_ctx.notifications, - struct mcp_session, - notifications_list); - dev_dbg(g_ctx.mcd, "pop %x\n", session->id); - notif_queue_push(session->id); - list_del_init(&session->notifications_list); - flushed = true; - } - - return flushed; -} - -bool mcp_notifications_flush(void) -{ - bool flushed = false; - - mutex_lock(&mcp_ctx.notifications_mutex); - flushed = mcp_notifications_flush_nolock(); - mutex_unlock(&mcp_ctx.notifications_mutex); - return flushed; -} - -int mcp_notify(struct mcp_session *session) -{ - int ret = 0; - - if (!mcp_ctx.scheduler_cb) - return -EAGAIN; - - mutex_lock(&mcp_ctx.notifications_mutex); - if (session->id == SID_MCP) - dev_dbg(g_ctx.mcd, "notify MCP"); - else - dev_dbg(g_ctx.mcd, "notify %x", session->id); - - /* Notify TEE */ - if (!list_empty(&mcp_ctx.notifications) || notif_queue_full()) { - if (!list_empty(&session->notifications_list)) { - ret = -EAGAIN; - dev_dbg(g_ctx.mcd, "skip %x\n", session->id); - } else { - list_add(&session->notifications_list, - &mcp_ctx.notifications); - dev_dbg(g_ctx.mcd, "push %x\n", session->id); - } - - mcp_notifications_flush_nolock(); - - if (mcp_ctx.scheduler_cb(MCP_YIELD)) { - MCDRV_ERROR("MC_SMC_N_YIELD failed"); - ret = -EPROTO; - } - } else { - notif_queue_push(session->id); - if (mcp_ctx.scheduler_cb(MCP_NSIQ)) { - MCDRV_ERROR("MC_SMC_N_SIQ failed"); - ret = -EPROTO; - } - } - - mutex_unlock(&mcp_ctx.notifications_mutex); - return ret; -} - -static inline void handle_mcp_notif(uint32_t exit_code) -{ - dev_dbg(g_ctx.mcd, "notification from MCP ec %d\n", exit_code); - complete(&mcp_ctx.complete); -} - -static inline void handle_session_notif(uint32_t session_id, uint32_t exit_code) -{ - struct mcp_session *session = NULL, *s; - - dev_dbg(g_ctx.mcd, "notification from %x ec %d\n", session_id, - exit_code); - mutex_lock(&mcp_ctx.sessions_lock); - list_for_each_entry(s, &mcp_ctx.sessions, list) { - if (s->id == session_id) { - session = s; - break; - } - } - - if (session) { - /* TA has terminated */ - if (exit_code) { - /* Update exit code, or not */ - mutex_lock(&session->exit_code_lock); - /* - * In GP, the only way to recover the sessions exit code - * is to call TEEC_InvokeCommand which will notify. But - * notifying a dead session would change the exit code - * to ERR_SID_NOT_ACTIVE, hence the check below. - */ - if (!session->is_gp || !session->exit_code || - (exit_code != ERR_SID_NOT_ACTIVE)) - session->exit_code = exit_code; - - mutex_unlock(&session->exit_code_lock); - - /* Update state or schedule close worker */ - if (session->state == MCP_SESSION_CLOSE_PREPARE) - session->state = MCP_SESSION_CLOSE_NOTIFIED; - else if (session->state == MCP_SESSION_CLOSING_GP) - schedule_work(&session->close_work); - } - - /* Unblock waiter */ - complete(&session->completion); - } - mutex_unlock(&mcp_ctx.sessions_lock); - - /* Unknown session, probably being started */ - if (!session) { - mutex_lock(&mcp_ctx.unexp_notif_mutex); - mcp_ctx.unexp_notif.session_id = session_id; - mcp_ctx.unexp_notif.payload = exit_code; - mutex_unlock(&mcp_ctx.unexp_notif_mutex); - } -} - -static void mc_irq_worker(struct work_struct *data) -{ - struct notification_queue *rx = mcp_ctx.nq.rx; - - /* Deal with all pending notifications in one go */ - while ((rx->hdr.write_cnt - rx->hdr.read_cnt) > 0) { - struct notification nf; - - nf = rx->notification[rx->hdr.read_cnt++ % rx->hdr.queue_size]; - if (nf.session_id == SID_MCP) - handle_mcp_notif(nf.payload); - else - handle_session_notif(nf.session_id, nf.payload); - } - - /* - * Finished processing notifications. It does not matter whether - * there actually were any notification or not. S-SIQs can also - * be triggered by an SWd driver which was waiting for a FIQ. - * In this case the S-SIQ tells NWd that SWd is no longer idle - * an will need scheduling again. - */ - if (mcp_ctx.scheduler_cb) - mcp_ctx.scheduler_cb(MCP_NSIQ); -} - -/* - * This function represents the interrupt function of the mcDrvModule. - * It signals by incrementing of an event counter and the start of the read - * waiting queue, the read function a interrupt has occurred. - */ -static irqreturn_t irq_handler(int intr, void *arg) -{ - /* wake up thread to continue handling this interrupt */ - schedule_work(&irq_work); - return IRQ_HANDLED; -} - -void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands)) -{ - mcp_ctx.scheduler_cb = scheduler_cb; -} - -void mcp_register_crashhandler(void (*crashhandler_cb)(void)) -{ - mcp_ctx.crashhandler_cb = crashhandler_cb; -} - -int mcp_start(void) -{ - size_t q_len = ALIGN(2 * (sizeof(struct notification_queue_header) + - NQ_NUM_ELEMS * sizeof(struct notification)), 4); - int ret; - - /* Make sure we have an interrupt number before going on */ -#if defined(CONFIG_OF) - mcp_ctx.irq = irq_of_parse_and_map(g_ctx.mcd->of_node, 0); -#endif -#if defined(MC_INTR_SSIQ) - if (mcp_ctx.irq <= 0) - mcp_ctx.irq = MC_INTR_SSIQ; -#endif - - if (mcp_ctx.irq <= 0) { - MCDRV_ERROR("No IRQ number, aborting"); - return -EINVAL; - } - - /* Call the INIT fastcall to setup shared buffers */ - ret = mc_fc_init(virt_to_phys(mcp_ctx.base), - (uintptr_t)mcp_ctx.mcp_buffer - - (uintptr_t)mcp_ctx.base, - q_len, sizeof(*mcp_ctx.mcp_buffer)); - if (ret) - return ret; - - /* First empty N-SIQ to setup of the MCI structure */ - ret = mc_fc_nsiq(); - if (ret) - return ret; - - /* - * Wait until (uint16_t)-1) { - MCDRV_DBG_WARN("queues too large (more than 64k), sorry..."); - return -EINVAL; - } - - mcp_ctx.order = get_order(q_len + sizeof(*mcp_ctx.mcp_buffer)); - mci = __get_free_pages(GFP_USER | __GFP_ZERO, mcp_ctx.order); - if (!mci) - return -ENOMEM; - - mcp_ctx.nq.tx = (struct notification_queue *)mci; - mcp_ctx.nq.tx->hdr.queue_size = NQ_NUM_ELEMS; - mci += sizeof(struct notification_queue_header) + - mcp_ctx.nq.tx->hdr.queue_size * sizeof(struct notification); - - mcp_ctx.nq.rx = (struct notification_queue *)mci; - mcp_ctx.nq.rx->hdr.queue_size = NQ_NUM_ELEMS; - mci += sizeof(struct notification_queue_header) + - mcp_ctx.nq.rx->hdr.queue_size * sizeof(struct notification); - - mcp_ctx.mcp_buffer = (void *)ALIGN(mci, 4); - return 0; -} - -void mcp_exit(void) -{ - mark_mcp_dead(); - if (mcp_ctx.dump.off) - kfree(mcp_ctx.dump.buf); - - free_pages((unsigned long)mcp_ctx.base, mcp_ctx.order); -} diff --git a/drivers/gud/MobiCoreDriver/mcp.h b/drivers/gud/MobiCoreDriver/mcp.h deleted file mode 100644 index 0eefe573de8bf..0000000000000 --- a/drivers/gud/MobiCoreDriver/mcp.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _MC_MCP_H_ -#define _MC_MCP_H_ - -#include "mci/mcloadformat.h" /* struct identity */ - -/* Structure to hold the TA/driver descriptor to pass to MCP */ -struct tbase_object { - uint32_t length; /* Total length */ - uint32_t header_length; /* Length of header before payload */ - uint8_t data[]; /* Header followed by payload */ -}; - -/* Structure to hold all mapped buffer data to pass to MCP */ -struct mcp_buffer_map { - uint64_t phys_addr; /** Page-aligned physical address */ - uint64_t secure_va; /** Page-aligned physical address */ - uint32_t offset; /** Data offset inside the first page */ - uint32_t length; /** Length of the data */ - uint32_t type; /** Type of MMU */ -}; - -struct mcp_session { - /* Work descriptor to handle delayed closing, set by upper layer */ - struct work_struct close_work; - /* Sessions list (protected by mcp sessions_lock) */ - struct list_head list; - /* Notifications list (protected by mcp notifications_mutex) */ - struct list_head notifications_list; - /* Notification waiter lock */ - struct mutex notif_wait_lock; /* Only one at a time */ - /* Notification received */ - struct completion completion; - /* Notification lock */ - struct mutex exit_code_lock; - /* Last notification */ - int32_t exit_code; - /* Session id */ - uint32_t id; - /* Session state (protected by mcp sessions_lock) */ - enum mcp_session_state { - MCP_SESSION_RUNNING, - MCP_SESSION_CLOSE_PREPARE, - MCP_SESSION_CLOSE_NOTIFIED, - MCP_SESSION_CLOSING_GP, - MCP_SESSION_CLOSED, - } state; - /* This TA is of Global Platform type, set by upper layer */ - bool is_gp; - /* GP TAs have login information */ - struct identity identity; -}; - -/* Init for the mcp_session structure */ -void mcp_session_init(struct mcp_session *session, bool is_gp, - const struct identity *identity); -int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout); -int32_t mcp_session_exitcode(struct mcp_session *mcp_session); - -/* SWd suspend/resume */ -int mcp_suspend(void); -int mcp_resume(void); -bool mcp_suspended(void); - -/* Callback to scheduler registration */ -enum mcp_scheduler_commands { - MCP_YIELD, - MCP_NSIQ, -}; - -void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands)); -bool mcp_notifications_flush(void); -void mcp_register_crashhandler(void (*crashhandler_cb)(void)); - -/* - * Get the requested SWd sleep timeout value (ms) - * - if the timeout is -1, wait indefinitely - * - if the timeout is 0, re-schedule immediately (timeouts in µs in the SWd) - * - otherwise sleep for the required time - * returns true if sleep is required, false otherwise - */ -bool mcp_get_idle_timeout(int32_t *timeout); -void mcp_reset_idle_timeout(void); - -/* MCP commands */ -int mcp_get_version(struct mc_version_info *version_info); -int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *buffer_map); -int mcp_load_check(const struct tbase_object *obj, - const struct mcp_buffer_map *buffer_map); -int mcp_open_session(struct mcp_session *session, - const struct tbase_object *obj, - const struct mcp_buffer_map *map, - const struct mcp_buffer_map *tci_map); -int mcp_close_session(struct mcp_session *session); -int mcp_map(uint32_t session_id, struct mcp_buffer_map *buffer_map); -int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *buffer_map); -int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *buffer_maps); -int mcp_multiunmap(uint32_t session_id, - const struct mcp_buffer_map *buffer_maps); -int mcp_notify(struct mcp_session *mcp_session); - -/* MCP initialisation/cleanup */ -int mcp_init(void); -void mcp_exit(void); -int mcp_start(void); -void mcp_stop(void); - -#endif /* _MC_MCP_H_ */ diff --git a/drivers/gud/MobiCoreDriver/mmu.c b/drivers/gud/MobiCoreDriver/mmu.c deleted file mode 100644 index fc769be4d15db..0000000000000 --- a/drivers/gud/MobiCoreDriver/mmu.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" - -#include "mci/mcimcp.h" - -#include "platform.h" /* CONFIG_TRUSTONIC_TEE_LPAE */ -#include "main.h" -#include "debug.h" -#include "mcp.h" /* mcp_buffer_map */ -#include "mmu.h" - -#ifdef CONFIG_TRUSTONIC_TEE_LPAE -#define MMU_TYPE_PAGE (3 << 0) -#define MMU_BUFFERABLE BIT(2) /* AttrIndx[0] */ -#define MMU_CACHEABLE BIT(3) /* AttrIndx[1] */ -#define MMU_NS BIT(5) -#define MMU_AP_RW_ALL BIT(6) /* AP[2:1], RW, at any privilege level */ -#define MMU_EXT_SHARED (3 << 8) /* SH[1:0], inner shareable */ -#define MMU_EXT_AF BIT(10) /* Access Flag */ -#define MMU_EXT_NG BIT(11) -#define MMU_EXT_XN (((uint64_t)1) << 54) /* XN */ -#else -#define MMU_TYPE_EXT (3 << 0) /* v5 */ -#define MMU_TYPE_SMALL (2 << 0) -#define MMU_BUFFERABLE BIT(2) -#define MMU_CACHEABLE BIT(3) -#define MMU_EXT_AP0 BIT(4) -#define MMU_EXT_AP1 (2 << 4) -#define MMU_EXT_TEX(x) ((x) << 6) /* v5 */ -#define MMU_EXT_SHARED BIT(10) /* v6 */ -#define MMU_EXT_NG BIT(11) /* v6 */ -#endif - -/* - * MobiCore specific page tables for world shared memory. - * Linux uses shadow page tables, see arch/arm/include/asm/pgtable-2level. - * MobiCore uses the default ARM format. - * - * Number of page table entries in one L2 MMU table. This is ARM specific, an - * MMU table covers 1 MiB by using 256 entries referring to 4KiB pages each. - */ -#define L2_ENTRIES_MAX 256 - -/* - * Small buffers (below 1MiB) are mapped using the legacy L2 table, but bigger - * buffers now use a fake L1 table that holds 64-bit pointers to L2 tables. As - * this must be exactly one page, we can hold up to 512 entries. - */ -#define L1_ENTRIES_MAX 512 - -#ifdef CONFIG_TRUSTONIC_TEE_LPAE - -/* - * Secure world uses 64-bit physical addresses - */ -typedef u64 tbase_pte_t; - -/* - * Linux uses different mappings for SMP systems(the sharing flag is set for - * the pte. In order not to confuse things too much in Mobicore make sure the - * shared buffers have the same flags. This should also be done in SWD side. - */ -static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG | -#ifdef CONFIG_SMP - MMU_EXT_SHARED | -#endif /* CONFIG_SMP */ - MMU_EXT_XN | MMU_EXT_AF | MMU_AP_RW_ALL | - MMU_NS | MMU_TYPE_PAGE; - -#else /* CONFIG_TRUSTONIC_TEE_LPAE */ - -/* - * Secure world uses 32-bit physical addresses - */ -typedef u32 tbase_pte_t; - -/* - * Linux uses different mappings for SMP systems(the sharing flag is set for - * the pte. In order not to confuse things too much in Mobicore make sure the - * shared buffers have the same flags. This should also be done in SWD side. - */ -static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG | -#ifdef CONFIG_SMP - MMU_EXT_SHARED | MMU_EXT_TEX(1) | -#endif /* CONFIG_SMP */ - MMU_EXT_AP1 | MMU_EXT_AP0 | - MMU_TYPE_SMALL | MMU_TYPE_EXT; - -#endif /* !CONFIG_TRUSTONIC_TEE_LPAE */ - -/* - * Fake L1 MMU table. - */ -union l1_table { - u64 *pages_phys; /* Array of physical page addresses */ - unsigned long page; -}; - -/* - * L2 MMU table, which is more a L3 table in the LPAE case. - */ -union l2_table { - tbase_pte_t *ptes; /* Array of PTEs */ - unsigned long page; -}; - -/* - * MMU table allocated to the Daemon or a TLC describing a world shared - * buffer. - * When users map a malloc()ed area into SWd, a MMU table is allocated. - * In addition, the area of maximum 1MB virtual address space is mapped into - * the MMU table and a handle for this table is returned to the user. - */ -struct tbase_mmu { - union l2_table l2_tables[L1_ENTRIES_MAX]; /* L2 tables */ - size_t l2_tables_nr; /* Actual number of L2 tables */ - union l1_table l1_table; /* Fake L1 table */ - union l2_table l1_l2_table; /* L2 table for the L1 table */ - uint32_t offset; - uint32_t length; - bool user; /* Pages are from user space */ -}; - -static void free_all_pages(struct tbase_mmu *mmu_table) -{ - union l2_table *l2_table = &mmu_table->l2_tables[0]; - size_t i; - - for (i = 0; i < mmu_table->l2_tables_nr; i++, l2_table++) { - if (!l2_table->page) - break; - - free_page(l2_table->page); - } - - if (mmu_table->l1_l2_table.page) - free_page(mmu_table->l1_l2_table.page); - - if (mmu_table->l1_table.page) - free_page(mmu_table->l1_table.page); -} - -/* - * Create a MMU table for a buffer or trustlet. - */ -static inline int map_buffer(struct task_struct *task, const void *data, - unsigned int length, struct tbase_mmu *mmu_table) -{ - const void *reader = (const void *)((uintptr_t)data & PAGE_MASK); - struct page **pages; /* Same as above, conveniently typed */ - unsigned long pages_page; /* Page to contain the page pointers */ - size_t chunk; - unsigned long total_pages_nr; - int l1_entries_max; - int ret = 0; - - /* Check that we have enough space to map data */ - mmu_table->length = length; - mmu_table->offset = (uintptr_t)data & ~PAGE_MASK; - total_pages_nr = PAGE_ALIGN(mmu_table->offset + length) / PAGE_SIZE; - if (g_ctx.f_mem_ext) - l1_entries_max = L1_ENTRIES_MAX; - else - l1_entries_max = 1; - - if (total_pages_nr > (l1_entries_max * L2_ENTRIES_MAX)) { - dev_err(g_ctx.mcd, "data mapping exceeds %d pages", - l1_entries_max * L2_ENTRIES_MAX); - return -EINVAL; - } - - /* Get number of L2 tables needed */ - mmu_table->l2_tables_nr = (total_pages_nr + L2_ENTRIES_MAX - 1) / - L2_ENTRIES_MAX; - dev_dbg(g_ctx.mcd, "total_pages_nr %lu l2_tables_nr %zu", - total_pages_nr, mmu_table->l2_tables_nr); - - /* Get a page to store page pointers */ - pages_page = get_zeroed_page(GFP_KERNEL); - if (!pages_page) - return -ENOMEM; - - pages = (struct page **)pages_page; - - /* Allocate a page for the L1 table */ - if (mmu_table->l2_tables_nr > 1) { - tbase_pte_t *pte; - - mmu_table->l1_table.page = get_zeroed_page(GFP_KERNEL); - mmu_table->l1_l2_table.page = get_zeroed_page(GFP_KERNEL); - if (!mmu_table->l1_table.page || !mmu_table->l1_l2_table.page) { - ret = -ENOMEM; - goto end; - } - - /* Map it */ - pte = &mmu_table->l1_l2_table.ptes[0]; - *pte = virt_to_phys(mmu_table->l1_table.pages_phys); - *pte |= pte_flags; - } - - for (chunk = 0; chunk < mmu_table->l2_tables_nr; chunk++) { - unsigned long pages_nr, i; - tbase_pte_t *pte; - struct page **page_ptr; - - /* Size to map for this chunk */ - if (chunk == (mmu_table->l2_tables_nr - 1)) - pages_nr = ((total_pages_nr - 1) % L2_ENTRIES_MAX) + 1; - else - pages_nr = L2_ENTRIES_MAX; - - /* Allocate a page for the MMU descriptor */ - mmu_table->l2_tables[chunk].page = get_zeroed_page(GFP_KERNEL); - if (!mmu_table->l2_tables[chunk].page) { - ret = -ENOMEM; - goto end; - } - - /* Add page address to L1 table if needed */ - if (mmu_table->l1_table.page) - mmu_table->l1_table.pages_phys[chunk] = - virt_to_phys(mmu_table->l2_tables[chunk].ptes); - - /* Get pages */ - if (task) { - long gup_ret; - - /* Buffer was allocated in user space */ - down_read(&task->mm->mmap_sem); - gup_ret = get_user_pages(task, task->mm, - (uintptr_t)reader, pages_nr, - 1, 0, pages, 0); - reader += pages_nr * PAGE_SIZE; - up_read(&task->mm->mmap_sem); - if (gup_ret < 0) { - ret = gup_ret; - dev_err(g_ctx.mcd, - "failed to get user pages: %d", ret); - goto end; - } - - /* check if we could lock all pages. */ - if (gup_ret != pages_nr) { - dev_err(g_ctx.mcd, - "get_user_pages() failed, ret: %ld", - gup_ret); - release_pages(pages, gup_ret, 0); - ret = -ENOMEM; - goto end; - } - - mmu_table->user = true; - } else if (is_vmalloc_addr(data)) { - /* Buffer vmalloc'ed in kernel space */ - page_ptr = &pages[0]; - for (i = 0; i < pages_nr; i++) { - struct page *page = vmalloc_to_page(reader); - - if (!page) { - dev_err(g_ctx.mcd, - "failed to map address"); - ret = -EINVAL; - goto end; - } - - *page_ptr++ = page; - reader += PAGE_SIZE; - } - } else { - /* Buffer kmalloc'ed in kernel space */ - struct page *page = virt_to_page(reader); - - reader += pages_nr * PAGE_SIZE; - page_ptr = &pages[0]; - for (i = 0; i < pages_nr; i++) - *page_ptr++ = page++; - } - - /* Create MMU Table entries */ - page_ptr = &pages[0]; - pte = &mmu_table->l2_tables[chunk].ptes[0]; - for (i = 0; i < pages_nr; i++, page_ptr++, pte++) { - /* - * Create MMU table entry, see ARM MMU docu for details - * about flags stored in the lowest 12 bits. As a side - * reference, the Article "ARM's multiply-mapped memory - * mess" found in the collection at - * http://lwn.net/Articles/409032/ is also worth reading. - */ - unsigned long phys = page_to_phys(*page_ptr); -#if defined CONFIG_ARM64 && !defined CONFIG_TRUSTONIC_TEE_LPAE - if (phys & 0xffffffff00000000) { - dev_err(g_ctx.mcd, - "Pointer too big for non-LPAE: 0x%16lx", - phys); - ret = -EFAULT; - goto end; - } -#endif - *pte = phys; - *pte |= pte_flags; - } - } - -end: - if (ret) - free_all_pages(mmu_table); - - free_page(pages_page); - return ret; -} - -static inline void unmap_buffer(struct tbase_mmu *mmu_table) -{ - int t; - - dev_dbg(g_ctx.mcd, "clear MMU table, virt %p", mmu_table); - if (!mmu_table->user) - goto end; - - /* Release all locked user space pages */ - for (t = 0; t < mmu_table->l2_tables_nr; t++) { - tbase_pte_t *pte = mmu_table->l2_tables[t].ptes; - int i; - - for (i = 0; i < L2_ENTRIES_MAX; i++, pte++) { - struct page *page; - - /* If not all entries are used, unused ones are 0 */ - if (!*pte) - break; - - /* pte_page() cannot return NULL */ - page = pte_page(*pte); - dev_dbg(g_ctx.mcd, "MMU entry %d: 0x%llx, virt %p", - i, (u64)*pte, page); - - page_cache_release(page); - } - } - -end: - free_all_pages(mmu_table); -} - -/* - * Delete a MMU table. - */ -void tbase_mmu_delete(struct tbase_mmu *mmu) -{ - if (WARN(!mmu, "NULL mmu pointer given")) - return; - - unmap_buffer(mmu); - MCDRV_DBG("freed mmu %p: %s len %u off %u table %lx type L%d", - mmu, mmu->user ? "user" : "kernel", mmu->length, mmu->offset, - (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes : - mmu->l2_tables[0].ptes), - mmu->l1_table.page ? 1 : 2); - kfree(mmu); -} - -/* - * Allocate MMU table and map buffer into it. - * That is, create respective table entries. - */ -struct tbase_mmu *tbase_mmu_create(struct task_struct *task, - const void *addr, - unsigned int length) -{ - struct tbase_mmu *mmu; - int ret; - - /* Check input arguments */ - if (WARN(!addr, "data address is NULL")) - return ERR_PTR(-EINVAL); - - if (WARN(!length, "data length is 0")) - return ERR_PTR(-EINVAL); - - /* Allocate the struct */ - mmu = kmalloc(sizeof(*mmu), GFP_KERNEL | __GFP_ZERO); - if (!mmu) - return ERR_PTR(-ENOMEM); - - /* Create the MMU mapping for the data */ - ret = map_buffer(task, addr, length, mmu); - if (ret) { - kfree(mmu); - return ERR_PTR(ret); - } - - MCDRV_DBG("created mmu %p: %s addr %p len %u off %u table %lx type L%d", - mmu, mmu->user ? "user" : "kernel", addr, mmu->length, - mmu->offset, - (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes : - mmu->l2_tables[0].ptes), - mmu->l1_table.page ? 1 : 2); - return mmu; -} - -void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map) -{ - if (mmu->l1_table.page) { - map->phys_addr = virt_to_phys(mmu->l1_l2_table.ptes); - map->type = WSM_L1; - } else { - map->phys_addr = virt_to_phys(mmu->l2_tables[0].ptes); - map->type = WSM_L2; - } - - map->secure_va = 0; - map->offset = mmu->offset; - map->length = mmu->length; -} - -int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf) -{ - return kasnprintf(buf, - "\t\t\tmmu %p: %s len %u off %u table %lx type L%d\n", - mmu, mmu->user ? "user" : "kernel", mmu->length, - mmu->offset, - (uintptr_t)(mmu->l1_table.page ? - mmu->l1_l2_table.ptes : mmu->l2_tables[0].ptes), - mmu->l1_table.page ? 1 : 2); -} diff --git a/drivers/gud/MobiCoreDriver/mmu.h b/drivers/gud/MobiCoreDriver/mmu.h deleted file mode 100644 index 09efea480bef8..0000000000000 --- a/drivers/gud/MobiCoreDriver/mmu.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _TBASE_MEM_H_ -#define _TBASE_MEM_H_ - -struct tbase_mmu; -struct mcp_buffer_map; - -/* - * Allocate MMU table and map buffer into it. - * That is, create respective table entries. - */ -struct tbase_mmu *tbase_mmu_create(struct task_struct *task, - const void *wsm_buffer, - unsigned int wsm_len); - -/* - * Delete a used MMU table. - */ -void tbase_mmu_delete(struct tbase_mmu *mmu); - -/* - * Fill in buffer info for MMU table. - */ -void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map); - -/* - * Add info to debug buffer. - */ -int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf); - -#endif /* _TBASE_MEM_H_ */ diff --git a/drivers/gud/MobiCoreDriver/platform.h b/drivers/gud/MobiCoreDriver/platform.h deleted file mode 100644 index f9c801450f64e..0000000000000 --- a/drivers/gud/MobiCoreDriver/platform.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MC_PLATFORM_H_ -#define _MC_PLATFORM_H_ - -/* MobiCore Interrupt for Qualcomm (DT IRQ has priority if present) */ -#define MC_INTR_SSIQ 280 - -/* Use SMC for fastcalls */ -#define MC_SMC_FASTCALL - -#include - -/*--------------- Implementation -------------- */ -#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \ - defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8909) || \ - defined(CONFIG_ARCH_MSM8996) - -#include - -#if defined(CONFIG_ARM64) || defined(CONFIG_ARCH_MSM8916) - - #include - #include - #include - #include - #include - #include - - #define SCM_MOBIOS_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) \ - | 0x33000000) - - #define TZ_EXECUTIVE_EXT_ID_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_4( \ - TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ - TZ_SYSCALL_PARAM_TYPE_VAL, \ - TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ - TZ_SYSCALL_PARAM_TYPE_VAL) - -#endif - -#else -#include -#endif - -/* from following file */ -#define SCM_SVC_MOBICORE 250 -#define SCM_CMD_MOBICORE 1 - -static inline int smc_fastcall(void *fc_generic, size_t size) -{ -#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \ - defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8996) - if (is_scm_armv8()) { - struct scm_desc desc = {0}; - int ret; - void *scm_buf = NULL; - - scm_buf = kzalloc(PAGE_ALIGN(size), GFP_KERNEL); - if (!scm_buf) - return -ENOMEM; - memcpy(scm_buf, fc_generic, size); - dmac_flush_range(scm_buf, scm_buf + size); - - desc.arginfo = TZ_EXECUTIVE_EXT_ID_PARAM_ID; - desc.args[0] = virt_to_phys(scm_buf); - desc.args[1] = (u32)size; - desc.args[2] = virt_to_phys(scm_buf); - desc.args[3] = (u32)size; - - ret = scm_call2( - SCM_MOBIOS_FNID(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE), - &desc); - - dmac_flush_range(scm_buf, scm_buf + size); - - memcpy(fc_generic, scm_buf, size); - kfree(scm_buf); - return ret; - } -#endif - - return scm_call(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE, - fc_generic, size, - fc_generic, size); -} - -/* Fastcall value should be the one for armv7, even if on armv8, - * as long as the __aarch32__ flag is not activated in SW. - * But for 8996, architecture is armv8 with __aarch32__ in Sw. - */ -#if !defined(CONFIG_ARCH_MSM8996) -#define MC_ARMV7_FC -#endif - -#if defined(CONFIG_ARCH_MSM8996) -#define CONFIG_TRUSTONIC_TEE_LPAE -#endif - -/* - * Perform crypto clock enable/disable - * of clocks - * "bus_clk" - * "core_clk" - * "iface_clk" - */ -#if (!defined(CONFIG_ARCH_MSM8960) && !defined(CONFIG_ARCH_MSM8994)) || \ - defined(CONFIG_ARCH_MSM8996) -#define MC_CRYPTO_CLOCK_MANAGEMENT -#endif - -/* - * Perform clock enable/disable for clock "core_clk_src" - */ -#if defined(CONFIG_ARCH_MSM8916) || defined(CONFIG_ARCH_MSM8909) || \ - defined(CONFIG_ARCH_MSM8996) -#define MC_DEVICE_PROPNAME "qcom,mcd" -#if defined(MC_CRYPTO_CLOCK_MANAGEMENT) -#define MC_CLOCK_CORESRC_PROPNAME "qcom,ce-opp-freq" -#define MC_CLOCK_CORESRC_DEFAULTRATE 100000000 -#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */ -#endif - - -#if !defined(CONFIG_ARCH_MSM8996) -/* uid/gid behave like old kernels but with new types */ -/* This flag does not exist on 8996 3.10 kernel version */ -#if !defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) -#define MC_UIDGID_OLDSTYLE -#endif -/* Fastcall value should be the one for armv7, even if on armv8, - * as long as the __aarch32__ flag is not activated in SW. - * But for 8996, architecture is armv8 with __aarch32__ in Sw. - */ -#define MC_ARMV7_FC -#endif /* not CONFIG_ARCH_MSM8996 */ - -#endif /* _MC_PLATFORM_H_ */ - diff --git a/drivers/gud/MobiCoreDriver/pm.c b/drivers/gud/MobiCoreDriver/pm.c deleted file mode 100644 index 98310f73dfeab..0000000000000 --- a/drivers/gud/MobiCoreDriver/pm.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include - -#include "public/mc_linux.h" - -#include "platform.h" /* MC_PM_RUNTIME */ -#include "debug.h" -#include "scheduler.h" /* SWd suspend/resume commands */ -#include "pm.h" - -#ifdef MC_PM_RUNTIME -static struct pm_context { - struct notifier_block pm_notifier; -} pm_ctx; - -static int mc_suspend_notifier(struct notifier_block *nb, unsigned long event, - void *dummy) -{ - switch (event) { - case PM_SUSPEND_PREPARE: - return mc_scheduler_suspend(); - case PM_POST_SUSPEND: - return mc_scheduler_resume(); - } - - return 0; -} - - -/* CPI todo: inconsistent handling of ret in below 2 functions */ -int mc_pm_start(void) -{ - int ret = 0; - - pm_ctx.pm_notifier.notifier_call = mc_suspend_notifier; - ret = register_pm_notifier(&pm_ctx.pm_notifier); - MCDRV_DBG_VERBOSE("done, ret = %d", ret); - - return ret; -} - -void mc_pm_stop(void) -{ - unregister_pm_notifier(&pm_ctx.pm_notifier); -} - -#endif /* MC_PM_RUNTIME */ diff --git a/drivers/gud/MobiCoreDriver/pm.h b/drivers/gud/MobiCoreDriver/pm.h deleted file mode 100644 index 999599a70b1ab..0000000000000 --- a/drivers/gud/MobiCoreDriver/pm.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _MC_PM_H_ -#define _MC_PM_H_ - -#include "platform.h" /* MC_PM_RUNTIME */ - -#ifdef MC_PM_RUNTIME -/* Initialize Power Management */ -int mc_pm_start(void); -/* Free all Power Management resources*/ -void mc_pm_stop(void); -#else -static inline int mc_pm_start(void) -{ - return 0; -} - -static inline void mc_pm_stop(void) -{ -} -#endif - -#endif /* _MC_PM_H_ */ diff --git a/drivers/gud/MobiCoreDriver/public/mc_admin.h b/drivers/gud/MobiCoreDriver/public/mc_admin.h deleted file mode 100644 index 3a4078dd6fc30..0000000000000 --- a/drivers/gud/MobiCoreDriver/public/mc_admin.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef __MC_ADMIN_IOCTL_H__ -#define __MC_ADMIN_IOCTL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define MC_ADMIN_DEVNODE "mobicore" - -/* Driver/daemon commands */ -enum { - /* Command 0 is reserved */ - MC_DRV_GET_ROOT_CONTAINER = 1, - MC_DRV_GET_SP_CONTAINER = 2, - MC_DRV_GET_TRUSTLET_CONTAINER = 3, - MC_DRV_GET_TRUSTLET = 4, - MC_DRV_SIGNAL_CRASH = 5, -}; - -/* MobiCore IOCTL magic number */ -#define MC_IOC_MAGIC 'M' - -struct mc_admin_request { - uint32_t request_id; /* Unique request identifier */ - uint32_t command; /* Command to daemon */ - struct mc_uuid_t uuid; /* UUID of trustlet, if relevant */ - uint32_t is_gp; /* Whether trustlet is GP */ - uint32_t spid; /* SPID of trustlet, if relevant */ -}; - -struct mc_admin_response { - uint32_t request_id; /* Unique request identifier */ - uint32_t error_no; /* Errno from daemon */ - uint32_t spid; /* SPID of trustlet, if relevant */ - uint32_t service_type; /* Type of trustlet being returned */ - uint32_t length; /* Length of data to get */ - /* Any data follows */ -}; - -struct mc_admin_driver_info { - /* Version, and something else..*/ - uint32_t drv_version; - uint32_t initial_cmd_id; -}; - -struct mc_admin_load_info { - uint32_t spid; /* SPID of trustlet, if relevant */ - uint64_t address; /* Address of the data */ - uint32_t length; /* Length of data to get */ -}; - -#define MC_ADMIN_IO_GET_DRIVER_REQUEST \ - _IOR(MC_IOC_MAGIC, 0, struct mc_admin_request) -#define MC_ADMIN_IO_GET_INFO \ - _IOR(MC_IOC_MAGIC, 1, struct mc_admin_driver_info) -#define MC_ADMIN_IO_LOAD_DRIVER \ - _IOW(MC_IOC_MAGIC, 2, struct mc_admin_load_info) -#define MC_ADMIN_IO_LOAD_TOKEN \ - _IOW(MC_IOC_MAGIC, 3, struct mc_admin_load_info) -#define MC_ADMIN_IO_LOAD_CHECK \ - _IOW(MC_IOC_MAGIC, 4, struct mc_admin_load_info) - -#ifdef __cplusplus -} -#endif -#endif /* __MC_ADMIN_IOCTL_H__ */ diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux.h b/drivers/gud/MobiCoreDriver/public/mc_linux.h deleted file mode 100644 index 2368653f8890d..0000000000000 --- a/drivers/gud/MobiCoreDriver/public/mc_linux.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _MC_LINUX_H_ -#define _MC_LINUX_H_ - -#define MCDRVMODULEAPI_VERSION_MAJOR 2 -#define MCDRVMODULEAPI_VERSION_MINOR 1 - -#ifndef __KERNEL__ -#include -#endif - -#define MC_USER_DEVNODE "mobicore-user" - -/** Maximum length of MobiCore product ID string. */ -#define MC_PRODUCT_ID_LEN 64 - -/** Number of buffers that can be mapped at once */ -#define MC_MAP_MAX 4 - -/* - * Universally Unique Identifier (UUID) according to ISO/IEC 11578. - */ -struct mc_uuid_t { - uint8_t value[16]; /* Value of the UUID. */ -}; - -/* - * GP TA login types. - */ -enum mc_login_type { - TEEC_LOGIN_PUBLIC = 0, - TEEC_LOGIN_USER, - TEEC_LOGIN_GROUP, - TEEC_LOGIN_APPLICATION = 4, - TEEC_LOGIN_USER_APPLICATION, - TEEC_LOGIN_GROUP_APPLICATION, -}; - -/* - * GP TA identity structure. - */ -struct mc_identity { - enum mc_login_type login_type; - union { - uint8_t login_data[16]; - gid_t gid; /* Requested group id */ - struct { - uid_t euid; - uid_t ruid; - } uid; - }; -}; - -/* - * Data exchange structure of the MC_IO_OPEN_SESSION ioctl command. - */ -struct mc_ioctl_open_sess { - struct mc_uuid_t uuid; /* trustlet uuid */ - uint32_t is_gp_uuid; /* uuid is for GP TA */ - uint32_t sid; /* session id (out) */ - uint64_t tci; /* tci buffer pointer */ - uint32_t tcilen; /* tci length */ - struct mc_identity identity; /* GP TA identity */ -}; - -/* - * Data exchange structure of the MC_IO_OPEN_TRUSTLET ioctl command. - */ -struct mc_ioctl_open_trustlet { - uint32_t sid; /* session id (out) */ - uint32_t spid; /* trustlet spid */ - uint64_t buffer; /* trustlet binary pointer */ - uint32_t tlen; /* binary length */ - uint64_t tci; /* tci buffer pointer */ - uint32_t tcilen; /* tci length */ -}; - -/* - * Data exchange structure of the MC_IO_WAIT ioctl command. - */ -struct mc_ioctl_wait { - uint32_t sid; /* session id (in) */ - int32_t timeout; /* notification timeout */ -}; - -/* - * Data exchange structure of the MC_IO_ALLOC ioctl command. - */ -struct mc_ioctl_alloc { - uint32_t len; /* buffer length */ - uint32_t handle; /* user handle for the buffer (out) */ -}; - -/* - * Buffer mapping incoming and outgoing information. - */ -struct mc_ioctl_buffer { - uint64_t va; /* user space address of buffer */ - uint32_t len; /* buffer length */ - uint64_t sva; /* SWd virt address of buffer (out) */ -}; - -/* - * Data exchange structure of the MC_IO_MAP and MC_IO_UNMAP ioctl commands. - */ -struct mc_ioctl_map { - uint32_t sid; /* session id */ - struct mc_ioctl_buffer bufs[MC_MAP_MAX];/* buffers info */ -}; - -/* - * Data exchange structure of the MC_IO_ERR ioctl command. - */ -struct mc_ioctl_geterr { - uint32_t sid; /* session id */ - int32_t value; /* error value (out) */ -}; - -/* - * Global MobiCore Version Information. - */ -struct mc_version_info { - char product_id[MC_PRODUCT_ID_LEN]; /** Product ID string */ - uint32_t version_mci; /** Mobicore Control Interface */ - uint32_t version_so; /** Secure Objects */ - uint32_t version_mclf; /** MobiCore Load Format */ - uint32_t version_container; /** MobiCore Container Format */ - uint32_t version_mc_config; /** MobiCore Config. Block Format */ - uint32_t version_tl_api; /** MobiCore Trustlet API */ - uint32_t version_dr_api; /** MobiCore Driver API */ - uint32_t version_cmp; /** Content Management Protocol */ -}; - -/* - * defines for the ioctl mobicore driver module function call from user space. - */ -/* MobiCore IOCTL magic number */ -#define MC_IOC_MAGIC 'M' - -/* - * Implement corresponding functions from user api - */ -#define MC_IO_OPEN_SESSION \ - _IOWR(MC_IOC_MAGIC, 0, struct mc_ioctl_open_sess) -#define MC_IO_OPEN_TRUSTLET \ - _IOWR(MC_IOC_MAGIC, 1, struct mc_ioctl_open_trustlet) -#define MC_IO_CLOSE_SESSION _IO(MC_IOC_MAGIC, 2) -#define MC_IO_NOTIFY _IO(MC_IOC_MAGIC, 3) -#define MC_IO_WAIT _IOW(MC_IOC_MAGIC, 4, struct mc_ioctl_wait) -#define MC_IO_MAP _IOWR(MC_IOC_MAGIC, 5, struct mc_ioctl_map) -#define MC_IO_UNMAP _IOW(MC_IOC_MAGIC, 6, struct mc_ioctl_map) -#define MC_IO_ERR _IOWR(MC_IOC_MAGIC, 7, struct mc_ioctl_geterr) -#define MC_IO_FREEZE _IO(MC_IOC_MAGIC, 8) -#define MC_IO_VERSION _IOR(MC_IOC_MAGIC, 9, struct mc_version_info) -#define MC_IO_DR_VERSION _IOR(MC_IOC_MAGIC, 10, uint32_t) - -#endif /* _MC_LINUX_H_ */ diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h b/drivers/gud/MobiCoreDriver/public/mc_linux_api.h deleted file mode 100644 index 211bc2682b754..0000000000000 --- a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2013-2014 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MC_LINUX_API_H_ -#define _MC_LINUX_API_H_ - -/* - * Switch tbase active core to core_num, defined as linux - * core id - */ -int mc_switch_core(uint32_t core_num); - -/* - * Return tbase active core as Linux core id - */ -uint32_t mc_active_core(void); - -#endif /* _MC_LINUX_API_H_ */ diff --git a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h b/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h deleted file mode 100644 index 005099532d73a..0000000000000 --- a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ -#ifndef _MOBICORE_DRIVER_API_H_ -#define _MOBICORE_DRIVER_API_H_ - -#include "mc_linux.h" - -#define __MC_CLIENT_LIB_API - -/* - * Return values of MobiCore driver functions. - */ -enum mc_result { - /* Function call succeeded. */ - MC_DRV_OK = 0, - /* No notification available. */ - MC_DRV_NO_NOTIFICATION = 1, - /* Error during notification on communication level. */ - MC_DRV_ERR_NOTIFICATION = 2, - /* Function not implemented. */ - MC_DRV_ERR_NOT_IMPLEMENTED = 3, - /* No more resources available. */ - MC_DRV_ERR_OUT_OF_RESOURCES = 4, - /* Driver initialization failed. */ - MC_DRV_ERR_INIT = 5, - /* Unknown error. */ - MC_DRV_ERR_UNKNOWN = 6, - /* The specified device is unknown. */ - MC_DRV_ERR_UNKNOWN_DEVICE = 7, - /* The specified session is unknown.*/ - MC_DRV_ERR_UNKNOWN_SESSION = 8, - /* The specified operation is not allowed. */ - MC_DRV_ERR_INVALID_OPERATION = 9, - /* The response header from the MC is invalid. */ - MC_DRV_ERR_INVALID_RESPONSE = 10, - /* Function call timed out. */ - MC_DRV_ERR_TIMEOUT = 11, - /* Can not allocate additional memory. */ - MC_DRV_ERR_NO_FREE_MEMORY = 12, - /* Free memory failed. */ - MC_DRV_ERR_FREE_MEMORY_FAILED = 13, - /* Still some open sessions pending. */ - MC_DRV_ERR_SESSION_PENDING = 14, - /* MC daemon not reachable */ - MC_DRV_ERR_DAEMON_UNREACHABLE = 15, - /* The device file of the kernel module could not be opened. */ - MC_DRV_ERR_INVALID_DEVICE_FILE = 16, - /* Invalid parameter. */ - MC_DRV_ERR_INVALID_PARAMETER = 17, - /* Unspecified error from Kernel Module*/ - MC_DRV_ERR_KERNEL_MODULE = 18, - /* Error during mapping of additional bulk memory to session. */ - MC_DRV_ERR_BULK_MAPPING = 19, - /* Error during unmapping of additional bulk memory to session. */ - MC_DRV_ERR_BULK_UNMAPPING = 20, - /* Notification received, exit code available. */ - MC_DRV_INFO_NOTIFICATION = 21, - /* Set up of NWd connection failed. */ - MC_DRV_ERR_NQ_FAILED = 22, - /* Wrong daemon version. */ - MC_DRV_ERR_DAEMON_VERSION = 23, - /* Wrong container version. */ - MC_DRV_ERR_CONTAINER_VERSION = 24, - /* System Trustlet public key is wrong. */ - MC_DRV_ERR_WRONG_PUBLIC_KEY = 25, - /* Wrong container type(s). */ - MC_DRV_ERR_CONTAINER_TYPE_MISMATCH = 26, - /* Container is locked (or not activated). */ - MC_DRV_ERR_CONTAINER_LOCKED = 27, - /* SPID is not registered with root container. */ - MC_DRV_ERR_SP_NO_CHILD = 28, - /* UUID is not registered with sp container. */ - MC_DRV_ERR_TL_NO_CHILD = 29, - /* Unwrapping of root container failed. */ - MC_DRV_ERR_UNWRAP_ROOT_FAILED = 30, - /* Unwrapping of service provider container failed. */ - MC_DRV_ERR_UNWRAP_SP_FAILED = 31, - /* Unwrapping of Trustlet container failed. */ - MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED = 32, - /* No device associated with connection. */ - MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN = 33, - /* TA blob attestation is incorrect. */ - MC_DRV_ERR_TA_ATTESTATION_ERROR = 34, - /* Interrupted system call. */ - MC_DRV_ERR_INTERRUPTED_BY_SIGNAL = 35, - /* Service is blocked and opensession is thus not allowed. */ - MC_DRV_ERR_SERVICE_BLOCKED = 36, - /* Service is locked and opensession is thus not allowed. */ - MC_DRV_ERR_SERVICE_LOCKED = 37, - /* Service was killed by the TEE (due to an administrative command). */ - MC_DRV_ERR_SERVICE_KILLED = 38, - /* All permitted instances to the service are used */ - MC_DRV_ERR_NO_FREE_INSTANCES = 39, - /* TA blob header is incorrect. */ - MC_DRV_ERR_TA_HEADER_ERROR = 40, -}; - -/* - * Structure of Session Handle, includes the Session ID and the Device ID the - * Session belongs to. - * The session handle will be used for session-based MobiCore communication. - * It will be passed to calls which address a communication end point in the - * MobiCore environment. - */ -struct mc_session_handle { - uint32_t session_id; /* MobiCore session ID */ - uint32_t device_id; /* Device ID the session belongs to */ -}; - -/* - * Information structure about additional mapped Bulk buffer between the - * Trustlet Connector (NWd) and the Trustlet (SWd). This structure is - * initialized from a Trustlet Connector by calling mc_map(). - * In order to use the memory within a Trustlet the Trustlet Connector has to - * inform the Trustlet with the content of this structure via the TCI. - */ -struct mc_bulk_map { - /* The virtual address of the Bulk buffer regarding the address space - * of the Trustlet, already includes a possible offset! */ - uint32_t secure_virt_addr; - uint32_t secure_virt_len; /* Length of the mapped Bulk buffer */ -}; - -/* The default device ID */ -#define MC_DEVICE_ID_DEFAULT 0 -/* Wait infinite for a response of the MC. */ -#define MC_INFINITE_TIMEOUT ((int32_t)(-1)) -/* Do not wait for a response of the MC. */ -#define MC_NO_TIMEOUT 0 -/* TCI/DCI must not exceed 1MiB */ -#define MC_MAX_TCI_LEN 0x100000 - -/** - * mc_open_device() - Open a new connection to a MobiCore device. - * @device_id: Identifier for the MobiCore device to be used. - * MC_DEVICE_ID_DEFAULT refers to the default device. - * - * Initializes all device specific resources required to communicate with a - * MobiCore instance located on the specified device in the system. If the - * device does not exist the function will return MC_DRV_ERR_UNKNOWN_DEVICE. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_ERR_INVALID_OPERATION: device already opened - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon - * MC_DRV_ERR_UNKNOWN_DEVICE: device_id unknown - * MC_DRV_ERR_INVALID_DEVICE_FILE: kernel module under /dev/mobicore - * cannot be opened - */ -__MC_CLIENT_LIB_API enum mc_result mc_open_device(uint32_t device_id); - -/** - * mc_close_device() - Close the connection to a MobiCore device. - * @device_id: Identifier for the MobiCore device. - * - * When closing a device, active sessions have to be closed beforehand. - * Resources associated with the device will be released. - * The device may be opened again after it has been closed. - * - * MC_DEVICE_ID_DEFAULT refers to the default device. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid - * MC_DRV_ERR_SESSION_PENDING: a session is still open - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur - */ -__MC_CLIENT_LIB_API enum mc_result mc_close_device(uint32_t device_id); - -/** - * mc_open_session() - Open a new session to a Trustlet. - * @session: On success, the session data will be returned - * @uuid: UUID of the Trustlet to be opened - * @tci: TCI buffer for communicating with the Trustlet - * @tci_len: Length of the TCI buffer. Maximum allowed value - * is MC_MAX_TCI_LEN - * - * The Trustlet with the given UUID has to be available in the flash filesystem. - * - * Write MCP open message to buffer and notify MobiCore about the availability - * of a new command. - * - * Waits till the MobiCore responses with the new session ID (stored in the MCP - * buffer). - * - * Note that session.device_id has to be the device id of an opened device. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: session parameter is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur - * MC_DRV_ERR_NQ_FAILED: daemon returns an error - */ -__MC_CLIENT_LIB_API enum mc_result mc_open_session( - struct mc_session_handle *session, const struct mc_uuid_t *uuid, - uint8_t *tci, uint32_t tci_len); - -/** - * mc_open_trustlet() - Open a new session to the provided Trustlet. - * @session: On success, the session data will be returned - * @spid: Service Provider ID (for SP trustlets otherwise ignored) - * @trustlet Memory buffer containing the Trusted Application binary - * @trustlet_len Trusted Application length - * @tci: TCI buffer for communicating with the Trustlet - * @tci_len: Length of the TCI buffer. Maximum allowed value - * is MC_MAX_TCI_LEN - * - * Write MCP open message to buffer and notify MobiCore about the availability - * of a new command. - * - * Waits till the MobiCore responses with the new session ID (stored in the MCP - * buffer). - * - * Note that session.device_id has to be the device id of an opened device. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: session parameter is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur - * MC_DRV_ERR_NQ_FAILED: daemon returns an error - */ -__MC_CLIENT_LIB_API enum mc_result mc_open_trustlet( - struct mc_session_handle *session, uint32_t spid, - uint8_t *trustlet, uint32_t trustlet_len, uint8_t *tci, uint32_t len); - -/** - * mc_close_session() - Close a Trustlet session. - * @session: Session to be closed. - * - * Closes the specified MobiCore session. The call will block until the - * session has been closed. - * - * Device device_id has to be opened in advance. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: session parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur - * MC_DRV_ERR_INVALID_DEVICE_FILE: daemon cannot open Trustlet file - */ -__MC_CLIENT_LIB_API enum mc_result mc_close_session( - struct mc_session_handle *session); - -/** - * mc_notify() - Notify a session. - * @session: The session to be notified. - * - * Notifies the session end point about available message data. - * If the session parameter is correct, notify will always succeed. - * Corresponding errors can only be received by mc_wait_notification(). - * - * A session has to be opened in advance. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: session parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - */ -__MC_CLIENT_LIB_API enum mc_result mc_notify(struct mc_session_handle *session); - -/** - * mc_wait_notification() - Wait for a notification. - * @session: The session the notification should correspond to. - * @timeout: Time in milliseconds to wait - * (MC_NO_TIMEOUT : direct return, > 0 : milliseconds, - * MC_INFINITE_TIMEOUT : wait infinitely) - * - * Wait for a notification issued by the MobiCore for a specific session. - * The timeout parameter specifies the number of milliseconds the call will wait - * for a notification. - * - * If the caller passes 0 as timeout value the call will immediately return. - * If timeout value is below 0 the call will block until a notification for the - * session has been received. - * - * If timeout is below 0, call will block. - * - * Caller has to trust the other side to send a notification to wake him up - * again. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_ERR_TIMEOUT: no notification arrived in time - * MC_DRV_INFO_NOTIFICATION: a problem with the session was - * encountered. Get more details with - * mc_get_session_error_code() - * MC_DRV_ERR_NOTIFICATION: a problem with the socket occurred - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - */ -__MC_CLIENT_LIB_API enum mc_result mc_wait_notification( - struct mc_session_handle *session, int32_t timeout); - -/** - * mc_malloc_wsm() - Allocate a block of world shared memory (WSM). - * @device_id: The ID of an opened device to retrieve the WSM from. - * @align: The alignment (number of pages) of the memory block - * (e.g. 0x00000001 for 4kb). - * @len: Length of the block in bytes. - * @wsm: Virtual address of the world shared memory block. - * @wsm_flags: Platform specific flags describing the memory to - * be allocated. - * - * The MC driver allocates a contiguous block of memory which can be used as - * WSM. - * This implicates that the allocated memory is aligned according to the - * alignment parameter. - * - * Always returns a buffer of size WSM_SIZE aligned to 4K. - * - * Align and wsm_flags are currently ignored - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid - * MC_DRV_ERR_NO_FREE_MEMORY: no more contiguous memory is - * available in this size or for this - * process - */ -__MC_CLIENT_LIB_API enum mc_result mc_malloc_wsm( - uint32_t device_id, - uint32_t align, - uint32_t len, - uint8_t **wsm, - uint32_t wsm_flags -); - -/** - * mc_free_wsm() - Free a block of world shared memory (WSM). - * @device_id: The ID to which the given address belongs - * @wsm: Address of WSM block to be freed - * - * The MC driver will free a block of world shared memory (WSM) previously - * allocated with mc_malloc_wsm(). The caller has to assure that the address - * handed over to the driver is a valid WSM address. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: when device id is invalid - * MC_DRV_ERR_FREE_MEMORY_FAILED: on failure - */ -__MC_CLIENT_LIB_API enum mc_result mc_free_wsm(uint32_t device_id, - uint8_t *wsm); - -/** - *mc_map() - Map additional bulk buffer between a Trustlet Connector (TLC) - * and the Trustlet (TL) for a session - * @session: Session handle with information of the device_id and - * the session_id. The given buffer is mapped to the - * session specified in the sessionHandle - * @buf: Virtual address of a memory portion (relative to TLC) - * to be shared with the Trustlet, already includes a - * possible offset! - * @len: length of buffer block in bytes. - * @map_info: Information structure about the mapped Bulk buffer - * between the TLC (NWd) and the TL (SWd). - * - * Memory allocated in user space of the TLC can be mapped as additional - * communication channel (besides TCI) to the Trustlet. Limitation of the - * Trustlet memory structure apply: only 6 chunks can be mapped with a maximum - * chunk size of 1 MiB each. - * - * It is up to the application layer (TLC) to inform the Trustlet - * about the additional mapped bulk memory. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur - * MC_DRV_ERR_BULK_MAPPING: buf is already uses as bulk buffer or - * when registering the buffer failed - */ -__MC_CLIENT_LIB_API enum mc_result mc_map( - struct mc_session_handle *session, void *buf, uint32_t len, - struct mc_bulk_map *map_info); - -/** - * mc_unmap() - Remove additional mapped bulk buffer between Trustlet Connector - * (TLC) and the Trustlet (TL) for a session - * @session: Session handle with information of the device_id and - * the session_id. The given buffer is unmapped from the - * session specified in the sessionHandle. - * @buf: Virtual address of a memory portion (relative to TLC) - * shared with the TL, already includes a possible offset! - * @map_info: Information structure about the mapped Bulk buffer - * between the TLC (NWd) and the TL (SWd) - * - * The bulk buffer will immediately be unmapped from the session context. - * - * The application layer (TLC) must inform the TL about unmapping of the - * additional bulk memory before calling mc_unmap! - * - * The clientlib currently ignores the len field in map_info. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur - * MC_DRV_ERR_BULK_UNMAPPING: buf was not registered earlier - * or when unregistering failed - */ -__MC_CLIENT_LIB_API enum mc_result mc_unmap( - struct mc_session_handle *session, void *buf, - struct mc_bulk_map *map_info); - -/* - * mc_get_session_error_code() - Get additional error information of the last - * error that occurred on a session. - * @session: Session handle with information of the device_id and - * the session_id - * @exit_code: >0 Trustlet has terminated itself with this value, - * <0 Trustlet is dead because of an error within the - * MobiCore (e.g. Kernel exception). See also MCI - * definition. - * - * After the request the stored error code will be deleted. - * - * Return codes: - * MC_DRV_OK: operation completed successfully - * MC_DRV_INVALID_PARAMETER: a parameter is invalid - * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid - * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid - */ -__MC_CLIENT_LIB_API enum mc_result mc_get_session_error_code( - struct mc_session_handle *session, int32_t *exit_code); - -#endif /* _MOBICORE_DRIVER_API_H_ */ diff --git a/drivers/gud/MobiCoreDriver/scheduler.c b/drivers/gud/MobiCoreDriver/scheduler.c deleted file mode 100644 index 444f839d8ad1d..0000000000000 --- a/drivers/gud/MobiCoreDriver/scheduler.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" - -#include "main.h" -#include "fastcall.h" -#include "debug.h" -#include "logging.h" -#include "mcp.h" -#include "scheduler.h" - -#define SCHEDULING_FREQ 5 /**< N-SIQ every n-th time */ - -static struct sched_ctx { - struct task_struct *thread; - bool thread_run; - struct completion idle_complete; /* Unblock scheduler thread */ - struct completion sleep_complete; /* Wait for sleep status */ - struct mutex sleep_mutex; /* Protect sleep request */ - struct mutex request_mutex; /* Protect all below */ - /* The order of this enum matters */ - enum { - NONE, /* No specific request */ - YIELD, /* Run the SWd */ - NSIQ, /* Schedule the SWd */ - SUSPEND, /* Suspend the SWd */ - RESUME, /* Resume the SWd */ - } request; - bool suspended; -} sched_ctx; - -static int mc_scheduler_command(int command) -{ - if (IS_ERR_OR_NULL(sched_ctx.thread)) - return -EFAULT; - - mutex_lock(&sched_ctx.request_mutex); - if (sched_ctx.request < command) { - sched_ctx.request = command; - complete(&sched_ctx.idle_complete); - } - - mutex_unlock(&sched_ctx.request_mutex); - return 0; -} - -static int mc_scheduler_pm_command(int command) -{ - int ret = -EPERM; - - if (IS_ERR_OR_NULL(sched_ctx.thread)) - return -EFAULT; - - mutex_lock(&sched_ctx.sleep_mutex); - - /* Send request */ - mc_scheduler_command(command); - - /* Wait for scheduler to reply */ - wait_for_completion(&sched_ctx.sleep_complete); - mutex_lock(&sched_ctx.request_mutex); - if (command == SUSPEND) { - if (sched_ctx.suspended) - ret = 0; - } else { - if (!sched_ctx.suspended) - ret = 0; - } - - mutex_unlock(&sched_ctx.request_mutex); - - mutex_unlock(&sched_ctx.sleep_mutex); - return ret; -} - -static int mc_dev_command(enum mcp_scheduler_commands command) -{ - switch (command) { - case MCP_YIELD: - return mc_scheduler_command(YIELD); - case MCP_NSIQ: - return mc_scheduler_command(NSIQ); - } - - return -EINVAL; -} - -int mc_scheduler_suspend(void) -{ - return mc_scheduler_pm_command(SUSPEND); -} - -int mc_scheduler_resume(void) -{ - return mc_scheduler_pm_command(RESUME); -} - -/* - * This thread, and only this thread, schedules the SWd. Hence, reading the idle - * status and its associated timeout is safe from race conditions. - */ -static int tee_scheduler(void *arg) -{ - int timeslice = 0; /* Actually scheduling period */ - int ret = 0; - - MCDRV_DBG("enter"); - while (1) { - int32_t timeout_ms = -1; - bool pm_request = false; - - if (sched_ctx.suspended || mcp_get_idle_timeout(&timeout_ms)) { - /* If timeout is 0 we keep scheduling the SWd */ - if (!timeout_ms) - mc_scheduler_command(NSIQ); - else if (timeout_ms < 0) - wait_for_completion(&sched_ctx.idle_complete); - else if (!wait_for_completion_timeout( - &sched_ctx.idle_complete, - msecs_to_jiffies(timeout_ms))) - /* Timed out, force SWd schedule */ - mc_scheduler_command(NSIQ); - } - - if (kthread_should_stop() || !sched_ctx.thread_run) - break; - - /* Get requested command if any */ - mutex_lock(&sched_ctx.request_mutex); - if (sched_ctx.request == YIELD) - /* Yield forced: increment timeslice */ - timeslice++; - else if (sched_ctx.request >= NSIQ) { - /* Force N_SIQ, also to suspend/resume SWd */ - timeslice = 0; - if (sched_ctx.request == SUSPEND) { - mcp_suspend(); - pm_request = true; - } else if (sched_ctx.request == RESUME) { - mcp_resume(); - pm_request = true; - } - } - - sched_ctx.request = NONE; - mutex_unlock(&sched_ctx.request_mutex); - - /* Reset timeout so we don't loop if SWd halted */ - mcp_reset_idle_timeout(); - if (timeslice--) { - /* Resume SWd from where it was */ - ret = mc_fc_yield(); - } else { - timeslice = SCHEDULING_FREQ; - /* Call SWd scheduler */ - ret = mc_fc_nsiq(); - } - - /* Always flush log buffer after the SWd has run */ - mc_logging_run(); - if (ret) - break; - - /* Should have suspended by now if requested */ - mutex_lock(&sched_ctx.request_mutex); - if (pm_request) { - sched_ctx.suspended = mcp_suspended(); - complete(&sched_ctx.sleep_complete); - } - - mutex_unlock(&sched_ctx.request_mutex); - - /* Flush pending notifications if possible */ - if (mcp_notifications_flush()) - complete(&sched_ctx.idle_complete); - } - - MCDRV_DBG("exit, ret is %d", ret); - return ret; -} - -int mc_scheduler_start(void) -{ - sched_ctx.thread_run = true; - sched_ctx.thread = kthread_run(tee_scheduler, NULL, "tee_scheduler"); - if (IS_ERR(sched_ctx.thread)) { - MCDRV_ERROR("tee_scheduler thread creation failed"); - return PTR_ERR(sched_ctx.thread); - } - - mcp_register_scheduler(mc_dev_command); - complete(&sched_ctx.idle_complete); - return 0; -} - -void mc_scheduler_stop(void) -{ - mcp_register_scheduler(NULL); - sched_ctx.thread_run = false; - complete(&sched_ctx.idle_complete); - kthread_stop(sched_ctx.thread); -} - -int mc_scheduler_init(void) -{ - init_completion(&sched_ctx.idle_complete); - init_completion(&sched_ctx.sleep_complete); - mutex_init(&sched_ctx.sleep_mutex); - mutex_init(&sched_ctx.request_mutex); - return 0; -} diff --git a/drivers/gud/MobiCoreDriver/scheduler.h b/drivers/gud/MobiCoreDriver/scheduler.h deleted file mode 100644 index c3c17f1c9017c..0000000000000 --- a/drivers/gud/MobiCoreDriver/scheduler.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef __MC_SCHEDULER_H__ -#define __MC_SCHEDULER_H__ - -int mc_scheduler_init(void); -static inline void mc_scheduler_exit(void) {} -int mc_scheduler_start(void); -void mc_scheduler_stop(void); -int mc_scheduler_suspend(void); -int mc_scheduler_resume(void); - -#endif /* __MC_SCHEDULER_H__ */ diff --git a/drivers/gud/MobiCoreDriver/session.c b/drivers/gud/MobiCoreDriver/session.c deleted file mode 100644 index 1dbb8900b2b3a..0000000000000 --- a/drivers/gud/MobiCoreDriver/session.c +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "public/mc_linux.h" -#include "public/mc_admin.h" - -#include "platform.h" /* MC_UIDGID_OLDSTYLE */ -#include "main.h" -#include "debug.h" -#include "mmu.h" -#include "mcp.h" -#include "client.h" /* *cbuf* */ -#include "session.h" -#include "mci/mcimcp.h" - -#define SHA1_HASH_SIZE 20 - -struct tbase_wsm { - /* Buffer NWd addr (uva or kva, used only for lookup) */ - uintptr_t va; - /* buffer length */ - uint32_t len; - /* Buffer SWd addr */ - uint32_t sva; - /* mmu L2 table */ - struct tbase_mmu *mmu; - /* possibly a pointer to a cbuf */ - struct tbase_cbuf *cbuf; - /* list node */ - struct list_head list; -}; - -/* - * Postponed closing for GP TAs. - * Implemented as a worker because cannot be executed from within isr_worker. - */ -static void session_close_worker(struct work_struct *work) -{ - struct mcp_session *mcp_session; - struct tbase_session *session; - - mcp_session = container_of(work, struct mcp_session, close_work); - session = container_of(mcp_session, struct tbase_session, mcp_session); - session_close(session); -} - -/* Forward declarations */ -static struct tbase_wsm *wsm_create(struct tbase_session *session, - uintptr_t buf, uint32_t len); -static void wsm_free(struct tbase_wsm *wsm); - -static int hash_path_and_data(char *hash, const void *data, - unsigned int data_len) -{ - struct mm_struct *mm = current->mm; - struct hash_desc desc; - struct scatterlist sg; - char *buf; - char *path; - unsigned int path_len; - int ret = 0; - - buf = (char *)__get_free_page(GFP_KERNEL); - if (!buf) - return -ENOMEM; - - down_read(&mm->mmap_sem); - if (!mm->exe_file) { - ret = -ENOENT; - goto end; - } - - path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE); - if (IS_ERR(path)) { - ret = PTR_ERR(path); - goto end; - } - - MCDRV_DBG("current process path = "); - { - char *c; - - for (c = path; *c; c++) - MCDRV_DBG("%c %d", *c, *c); - } - - path_len = strnlen(path, PAGE_SIZE); - MCDRV_DBG("path_len = %u", path_len); - desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { - ret = PTR_ERR(desc.tfm); - MCDRV_DBG("could not alloc hash = %d", ret); - goto end; - } - - desc.flags = 0; - sg_init_one(&sg, path, path_len); - crypto_hash_init(&desc); - crypto_hash_update(&desc, &sg, path_len); - if (data) { - MCDRV_DBG("current process path: hashing additional data\n"); - sg_init_one(&sg, data, data_len); - crypto_hash_update(&desc, &sg, data_len); - } - - crypto_hash_final(&desc, hash); - crypto_free_hash(desc.tfm); - -end: - up_read(&mm->mmap_sem); - free_page((unsigned long)buf); - - return ret; -} - -static int check_prepare_identity(const struct mc_identity *identity, - struct identity *mcp_identity) -{ - struct mc_identity *mcp_id = (struct mc_identity *)mcp_identity; - uint8_t hash[SHA1_HASH_SIZE]; - bool application = false; - const void *data; - unsigned int data_len; - - /* Mobicore doesn't support GP client authentication. */ - if (!g_ctx.f_client_login && - (identity->login_type != TEEC_LOGIN_PUBLIC)) { - MCDRV_DBG_WARN("Unsupported login type %d", - identity->login_type); - return -EINVAL; - } - - /* Copy login type */ - mcp_identity->login_type = identity->login_type; - - /* Fill in uid field */ - if ((identity->login_type == TEEC_LOGIN_USER) || - (identity->login_type == TEEC_LOGIN_USER_APPLICATION)) { - /* Set euid and ruid of the process. */ -#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE) - mcp_id->uid.euid = current_euid(); - mcp_id->uid.ruid = current_uid(); -#else - mcp_id->uid.euid = current_euid().val; - mcp_id->uid.ruid = current_uid().val; -#endif - } - - /* Check gid field */ - if ((identity->login_type == TEEC_LOGIN_GROUP) || - (identity->login_type == TEEC_LOGIN_GROUP_APPLICATION)) { -#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE) - gid_t gid = identity->gid; -#else - kgid_t gid = { - .val = identity->gid, - }; -#endif - /* Check if gid is one of: egid of the process, its rgid or one - * of its supplementary groups */ - if (!in_egroup_p(gid) && !in_group_p(gid)) { - MCDRV_DBG("group %d not allowed", identity->gid); - return -EACCES; - } - - MCDRV_DBG("group %d found", identity->gid); - mcp_id->gid = identity->gid; - } - - switch (identity->login_type) { - case TEEC_LOGIN_PUBLIC: - case TEEC_LOGIN_USER: - case TEEC_LOGIN_GROUP: - break; - case TEEC_LOGIN_APPLICATION: - application = true; - data = NULL; - data_len = 0; - break; - case TEEC_LOGIN_USER_APPLICATION: - application = true; - data = &mcp_id->uid; - data_len = sizeof(mcp_id->uid); - break; - case TEEC_LOGIN_GROUP_APPLICATION: - application = true; - data = &identity->gid; - data_len = sizeof(identity->gid); - break; - default: - /* Any other login_type value is invalid. */ - MCDRV_DBG_WARN("Invalid login type"); - return -EINVAL; - } - - if (application) { - if (hash_path_and_data(hash, data, data_len)) { - MCDRV_DBG("error in hash calculation"); - return -EAGAIN; - } - - memcpy(&mcp_id->login_data, hash, sizeof(mcp_id->login_data)); - } - - return 0; -} - -/* - * Create a session object. - * Note: object is not attached to client yet. - */ -struct tbase_session *session_create(struct tbase_client *client, bool is_gp, - struct mc_identity *identity) -{ - struct tbase_session *session; - struct identity mcp_identity; - - if (is_gp) { - /* Check identity method and data. */ - int ret = check_prepare_identity(identity, &mcp_identity); - - if (ret) - return ERR_PTR(ret); - } - - /* Allocate session object */ - session = kzalloc(sizeof(*session), GFP_KERNEL); - if (!session) - return ERR_PTR(-ENOMEM); - - mutex_init(&session->close_lock); - /* Initialise object members */ - mcp_session_init(&session->mcp_session, is_gp, &mcp_identity); - INIT_WORK(&session->mcp_session.close_work, session_close_worker); - session->client = client; - kref_init(&session->kref); - INIT_LIST_HEAD(&session->list); - mutex_init(&session->wsms_lock); - INIT_LIST_HEAD(&session->wsms); - MCDRV_DBG("created session %p: client %p", session, session->client); - return session; -} - -int session_open(struct tbase_session *session, const struct tbase_object *obj, - const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len) -{ - struct mcp_buffer_map map; - - tbase_mmu_buffer(obj_mmu, &map); - /* Create wsm object for tci */ - if (tci && len) { - struct tbase_wsm *wsm; - struct mcp_buffer_map tci_map; - int ret = 0; - - mutex_lock(&session->wsms_lock); - wsm = wsm_create(session, tci, len); - if (IS_ERR(wsm)) - ret = PTR_ERR(wsm); - - mutex_unlock(&session->wsms_lock); - if (ret) - return ret; - - tbase_mmu_buffer(wsm->mmu, &tci_map); - ret = mcp_open_session(&session->mcp_session, obj, &map, - &tci_map); - if (ret) { - mutex_lock(&session->wsms_lock); - wsm_free(wsm); - mutex_unlock(&session->wsms_lock); - } - - return ret; - } - - if (tci || len) { - MCDRV_ERROR("Tci pointer and length are incoherent"); - return -EINVAL; - } - - return mcp_open_session(&session->mcp_session, obj, &map, NULL); -} - -/* - * Close TA and unreference session object. - * Object will be freed if reference reaches 0. - * Session object is assumed to have been removed from main list, which means - * that session_close cannot be called anymore. - */ -int session_close(struct tbase_session *session) -{ - int ret = 0; - - if (!session) - return -ENXIO; - - mutex_lock(&session->close_lock); - switch (mcp_close_session(&session->mcp_session)) { - case 0: - /* TA is closed, remove from closing list */ - mutex_lock(&g_ctx.closing_lock); - list_del(&session->list); - mutex_unlock(&g_ctx.closing_lock); - /* Remove the ref we took on creation, exit if session freed */ - if (session_put(session)) - return 0; - - break; - case -EBUSY: - /* - * (GP) TA needs time to close. The "TA closed" notification - * will trigger a new call to session_close(). - * Return OK but do not unref. - */ - break; - default: - MCDRV_ERROR("Failed to close session %x in SWd", - session->mcp_session.id); - ret = -EPERM; - } - - mutex_unlock(&session->close_lock); - return ret; -} - -/* - * Free session object and all objects it contains (wsm). - */ -static void session_free(struct kref *kref) -{ - struct tbase_session *session; - struct tbase_wsm *wsm, *next; - - /* Remove remaining shared buffers (unmapped in SWd by mcp_close) */ - session = container_of(kref, struct tbase_session, kref); - list_for_each_entry_safe(wsm, next, &session->wsms, list) { - MCDRV_DBG("session %p: free wsm %p", session, wsm); - wsm_free(wsm); - } - - MCDRV_DBG("freed session %p: client %p id %x", - session, session->client, session->mcp_session.id); - kfree(session); -} - -/* - * Unreference session. - * Free session object if reference reaches 0. - */ -int session_put(struct tbase_session *session) -{ - return kref_put(&session->kref, session_free); -} - -/* - * Send a notification to TA - */ -int session_notify_swd(struct tbase_session *session) -{ - if (!session) { - MCDRV_ERROR("Session pointer is null"); - return -EINVAL; - } - - return mcp_notify(&session->mcp_session); -} - -/* - * Read and clear last notification received from TA - */ -int32_t session_exitcode(struct tbase_session *session) -{ - return mcp_session_exitcode(&session->mcp_session); -} - -/* - * Free a WSM object - */ -static void wsm_free(struct tbase_wsm *wsm) -{ - /* Remove wsm from its parent session's list */ - list_del(&wsm->list); - /* Free MMU table */ - if (!IS_ERR_OR_NULL(wsm->mmu)) - tbase_mmu_delete(wsm->mmu); - - /* Unref cbuf if applicable */ - if (wsm->cbuf) - tbase_cbuf_put(wsm->cbuf); - - /* Delete wsm object */ - MCDRV_DBG("freed wsm %p: mmu %p cbuf %p va %lx len %u", - wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); - kfree(wsm); -} - -static struct tbase_wsm *wsm_create(struct tbase_session *session, - uintptr_t buf, uint32_t len) -{ - struct tbase_wsm *wsm; - struct task_struct *task = NULL; - uintptr_t va; - int ret; - - /* Allocate structure */ - wsm = kzalloc(sizeof(*wsm), GFP_KERNEL); - if (!wsm) { - ret = -ENOMEM; - goto err_no_wsm; - } - - /* Add wsm to list so destroy can find it */ - list_add(&wsm->list, &session->wsms); - - /* Check if buffer is contained in a cbuf */ - wsm->cbuf = tbase_cbuf_get_by_addr(session->client, buf); - if (wsm->cbuf) { - uintptr_t offset; - - if (client_is_kernel(session->client)) - offset = buf - tbase_cbuf_addr(wsm->cbuf); - else - offset = buf - tbase_cbuf_uaddr(wsm->cbuf); - - if ((offset + len) > tbase_cbuf_len(wsm->cbuf)) { - ret = -EINVAL; - MCDRV_ERROR("crosses cbuf boundary"); - goto err; - } - /* Provide kernel virtual address */ - va = tbase_cbuf_addr(wsm->cbuf) + offset; - } else { - /* Not a cbuf. va is uva or kva depending on client. */ - /* Provide "task" if client is user */ - va = buf; - if (!client_is_kernel(session->client)) - task = current; - } - - /* Build MMU table for buffer */ - wsm->mmu = tbase_mmu_create(task, (void *)va, len); - if (IS_ERR(wsm->mmu)) { - ret = PTR_ERR(wsm->mmu); - goto err; - } - - wsm->va = buf; - wsm->len = len; - MCDRV_DBG("created wsm %p: mmu %p cbuf %p va %lx len %u", - wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); - goto end; - -err: - wsm_free(wsm); -err_no_wsm: - wsm = ERR_PTR(ret); -end: - return wsm; -} - -static inline int wsm_check(struct tbase_session *session, - struct mc_ioctl_buffer *buf) -{ - struct tbase_wsm *wsm; - - list_for_each_entry(wsm, &session->wsms, list) { - if ((buf->va < (wsm->va + wsm->len)) && - ((buf->va + buf->len) > wsm->va)) { - MCDRV_ERROR("buffer %lx overlaps with existing wsm", - wsm->va); - return -EADDRINUSE; - } - } - - return 0; -} - -static inline struct tbase_wsm *wsm_find(struct tbase_session *session, - uintptr_t va) -{ - struct tbase_wsm *wsm; - - list_for_each_entry(wsm, &session->wsms, list) - if (wsm->va == va) - return wsm; - - return NULL; -} - -static inline int wsm_info(struct tbase_wsm *wsm, struct kasnprintf_buf *buf) -{ - ssize_t ret; - - ret = kasnprintf(buf, "\t\twsm %p: mmu %p cbuf %p va %lx len %u\n", - wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); - if (ret < 0) - return ret; - - if (wsm->mmu) { - ret = tbase_mmu_info(wsm->mmu, buf); - if (ret < 0) - return ret; - } - - return 0; -} - -/* - * Share buffers with SWd and add corresponding WSM objects to session. - */ -int session_wsms_add(struct tbase_session *session, - struct mc_ioctl_buffer *bufs) -{ - struct mc_ioctl_buffer *buf; - struct mcp_buffer_map maps[MC_MAP_MAX]; - struct mcp_buffer_map *map; - int i, ret = 0; - uint32_t n_null_buf = 0; - - /* Check parameters */ - if (!session) - return -ENXIO; - - /* Lock the session */ - mutex_lock(&session->wsms_lock); - - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { - if (!buf->va) { - n_null_buf++; - continue; - } - - /* Avoid mapping overlaps */ - if (wsm_check(session, buf)) { - ret = -EADDRINUSE; - MCDRV_ERROR("maps[%d] va=%llx already map'd", i, - buf->va); - goto unlock; - } - } - - if (n_null_buf >= MC_MAP_MAX) { - ret = -EINVAL; - MCDRV_ERROR("va=NULL"); - goto unlock; - } - - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { - struct tbase_wsm *wsm; - - if (!buf->va) { - map->type = WSM_INVALID; - continue; - } - - wsm = wsm_create(session, buf->va, buf->len); - if (IS_ERR(wsm)) { - ret = PTR_ERR(wsm); - MCDRV_ERROR("maps[%d] va=%llx create failed: %d", i, - buf->va, ret); - goto end; - } - - tbase_mmu_buffer(wsm->mmu, map); - MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u", i, buf->va, - map->type, map->phys_addr, map->offset, map->length); - } - - /* Map buffers */ - if (g_ctx.f_multimap) { - /* Send MCP message to map buffers in SWd */ - ret = mcp_multimap(session->mcp_session.id, maps); - if (ret) - MCDRV_ERROR("multimap failed: %d", ret); - } else { - /* Map each buffer */ - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, - map++) { - if (!buf->va) - continue; - - /* Send MCP message to map buffer in SWd */ - ret = mcp_map(session->mcp_session.id, map); - if (ret) { - MCDRV_ERROR("maps[%d] va=%llx map failed: %d", - i, buf->va, ret); - break; - } - } - } - -end: - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { - struct tbase_wsm *wsm = wsm_find(session, buf->va); - - if (!buf->va) - continue; - - if (ret) { - if (!wsm) - break; - - /* Destroy mapping */ - wsm_free(wsm); - } else { - /* Store mapping */ - buf->sva = map->secure_va; - wsm->sva = buf->sva; - MCDRV_DBG("maps[%d] va=%llx map'd len=%u sva=%llx", - i, buf->va, buf->len, buf->sva); - } - } - -unlock: - /* Unlock the session */ - mutex_unlock(&session->wsms_lock); - return ret; -} - -/* - * Stop sharing buffers and delete corrsponding WSM objects. - */ -int session_wsms_remove(struct tbase_session *session, - const struct mc_ioctl_buffer *bufs) -{ - const struct mc_ioctl_buffer *buf; - struct mcp_buffer_map maps[MC_MAP_MAX]; - struct mcp_buffer_map *map; - int i, ret = 0; - uint32_t n_null_buf = 0; - - if (!session) { - MCDRV_ERROR("session pointer is null"); - return -EINVAL; - } - - /* Lock the session */ - mutex_lock(&session->wsms_lock); - - /* Find, check and map buffer */ - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { - struct tbase_wsm *wsm; - - if (!buf->va) { - n_null_buf++; - map->secure_va = 0; - continue; - } - - wsm = wsm_find(session, buf->va); - if (!wsm) { - ret = -EADDRNOTAVAIL; - MCDRV_ERROR("maps[%d] va=%llx not found", i, - buf->va); - goto out; - } - - /* Check input params consistency */ - /* TODO: fix the spec, "len" is NOT ignored anymore */ - if ((wsm->sva != buf->sva) || (wsm->len != buf->len)) { - MCDRV_ERROR("maps[%d] va=%llx no match: %x != %llx", - i, buf->va, wsm->sva, buf->sva); - MCDRV_ERROR("maps[%d] va=%llx no match: %u != %u", - i, buf->va, wsm->len, buf->len); - ret = -EINVAL; - goto out; - } - - tbase_mmu_buffer(wsm->mmu, map); - map->secure_va = buf->sva; - MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u s:%llx", i, - buf->va, map->type, map->phys_addr, map->offset, - map->length, map->secure_va); - } - - if (n_null_buf >= MC_MAP_MAX) { - ret = -EINVAL; - MCDRV_ERROR("va=NULL"); - goto out; - } - - if (g_ctx.f_multimap) { - /* Send MCP command to unmap buffers in SWd */ - ret = mcp_multiunmap(session->mcp_session.id, maps); - if (ret) - MCDRV_ERROR("mcp_multiunmap failed: %d", ret); - } else { - for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; - i++, buf++, map++) { - if (!buf->va) - continue; - - /* Send MCP command to unmap buffer in SWd */ - ret = mcp_unmap(session->mcp_session.id, map); - if (ret) { - MCDRV_ERROR("maps[%d] va=%llx unmap failed: %d", - i, buf->va, ret); - break; - } - } - } - - for (i = 0, buf = bufs; i < MC_MAP_MAX; i++, buf++) { - struct tbase_wsm *wsm = wsm_find(session, buf->va); - - if (!wsm) - break; - - /* Free wsm */ - wsm_free(wsm); - MCDRV_DBG("maps[%d] va=%llx unmap'd len=%u sva=%llx", i, - buf->va, buf->len, buf->sva); - } - -out: - mutex_unlock(&session->wsms_lock); - return ret; -} - -/* - * Sleep until next notification from SWd. - */ -int session_waitnotif(struct tbase_session *session, int32_t timeout) -{ - return mcp_session_waitnotif(&session->mcp_session, timeout); -} - -int session_info(struct tbase_session *session, struct kasnprintf_buf *buf) -{ - struct tbase_wsm *wsm; - int32_t exit_code = mcp_session_exitcode(&session->mcp_session); - int ret; - - ret = kasnprintf(buf, "\tsession %p: %x rc %d\n", session, - session->mcp_session.id, exit_code); - if (ret < 0) - return ret; - - /* WMSs */ - mutex_lock(&session->wsms_lock); - if (list_empty(&session->wsms)) - goto done; - - list_for_each_entry(wsm, &session->wsms, list) { - ret = wsm_info(wsm, buf); - if (ret < 0) - goto done; - } - -done: - mutex_unlock(&session->wsms_lock); - if (ret < 0) - return ret; - - return 0; -} diff --git a/drivers/gud/MobiCoreDriver/session.h b/drivers/gud/MobiCoreDriver/session.h deleted file mode 100644 index aec0c09ae9c9a..0000000000000 --- a/drivers/gud/MobiCoreDriver/session.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2015 TRUSTONIC LIMITED - * 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 - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#ifndef _SESSION_H_ -#define _SESSION_H_ - -#include - -#include "mcp.h" - -struct tbase_object; -struct tbase_mmu; -struct mc_ioctl_buffer; - -struct tbase_session { - /* Session list lock */ - struct mutex close_lock; - /* MCP session descriptor (MUST BE FIRST) */ - struct mcp_session mcp_session; - /* Owner */ - struct tbase_client *client; - /* Number of references kept to this object */ - struct kref kref; - /* The list entry to attach to session list of owner */ - struct list_head list; - /* Session WSMs lock */ - struct mutex wsms_lock; - /* List of WSMs for a session */ - struct list_head wsms; -}; - -struct tbase_session *session_create(struct tbase_client *client, bool is_gp, - struct mc_identity *identity); -int session_open(struct tbase_session *session, const struct tbase_object *obj, - const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len); -int session_close(struct tbase_session *session); -static inline void session_get(struct tbase_session *session) -{ - kref_get(&session->kref); -} - -int session_put(struct tbase_session *session); -int session_wsms_add(struct tbase_session *session, - struct mc_ioctl_buffer *bufs); -int session_wsms_remove(struct tbase_session *session, - const struct mc_ioctl_buffer *bufs); -int32_t session_exitcode(struct tbase_session *session); -int session_notify_swd(struct tbase_session *session); -int session_waitnotif(struct tbase_session *session, int32_t timeout); -int session_info(struct tbase_session *session, struct kasnprintf_buf *buf); - -#endif /* _SESSION_H_ */ diff --git a/drivers/gud/setupDrivers.sh b/drivers/gud/setupDrivers.sh deleted file mode 100644 index 994e83e8d9517..0000000000000 --- a/drivers/gud/setupDrivers.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -export COMP_PATH_ROOT=$(dirname $(readlink -f $BASH_SOURCE)) #set this to the absolute path of the folder containing this file - -# This part has to be set by the customer -# To be set, absolute path of kernel folder -export LINUX_PATH= -# To be set, absolute path! CROSS_COMPILE variable needed by kernel eg /home/user/arm-2009q3/bin/arm-none-linux-gnueabi- -export CROSS_COMPILE= -# To be set, build mode debug or release -export MODE=debug -# To be set, the absolute path to the Linux Android NDK -export NDK_PATH= - -# Global variables needed by build scripts -export COMP_PATH_Logwrapper=$COMP_PATH_ROOT/Logwrapper/Out -export COMP_PATH_MobiCore=$COMP_PATH_ROOT/MobiCore/Out -export COMP_PATH_MobiCoreDriverMod=$COMP_PATH_ROOT/mobicore_driver/Out -export COMP_PATH_MobiCoreDriverLib=$COMP_PATH_ROOT/daemon/Out -export COMP_PATH_AndroidNdkLinux=$NDK_PATH