diff --git a/drivers/misc/compat_qseecom.c b/drivers/misc/compat_qseecom.c index 8a086845369..f526f7827bd 100644 --- a/drivers/misc/compat_qseecom.c +++ b/drivers/misc/compat_qseecom.c @@ -325,6 +325,41 @@ static int compat_get_qseecom_qteec_req( return err; } +static int compat_get_qseecom_qteec_modfd_req( + struct compat_qseecom_qteec_modfd_req __user *data32, + struct qseecom_qteec_modfd_req __user *data) +{ + compat_uptr_t req_ptr; + compat_ulong_t req_len; + compat_uptr_t resp_ptr; + compat_ulong_t resp_len; + compat_long_t fd; + compat_ulong_t cmd_buf_offset; + int err, i; + + err = get_user(req_ptr, &data32->req_ptr); + data->req_ptr = NULL; + err |= put_user(req_ptr, (compat_uptr_t *)&data->req_ptr); + err |= get_user(req_len, &data32->req_len); + err |= put_user(req_len, &data->req_len); + + err |= get_user(resp_ptr, &data32->resp_ptr); + data->resp_ptr = NULL; + err |= put_user(resp_ptr, (compat_uptr_t *)&data->resp_ptr); + err |= get_user(resp_len, &data32->resp_len); + err |= put_user(resp_len, &data->resp_len); + + for (i = 0; i < MAX_ION_FD; i++) { + err |= get_user(fd, &data32->ifd_data[i].fd); + err |= put_user(fd, &data->ifd_data[i].fd); + err |= get_user(cmd_buf_offset, + &data32->ifd_data[i].cmd_buf_offset); + err |= put_user(cmd_buf_offset, + &data->ifd_data[i].cmd_buf_offset); + } + return err; +} + static int compat_get_int(compat_int_t __user *data32, int __user *data) { @@ -457,6 +492,8 @@ static unsigned int convert_cmd(unsigned int cmd) return QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ; case COMPAT_QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ: return QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ; + case COMPAT_QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: + return QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ; default: return cmd; } @@ -477,7 +514,7 @@ long compat_qseecom_ioctl(struct file *file, case COMPAT_QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: { return qseecom_ioctl(file, convert_cmd(cmd), 0); } - + break; case COMPAT_QSEECOM_IOCTL_REGISTER_LISTENER_REQ: { struct compat_qseecom_register_listener_req __user *data32; struct qseecom_register_listener_req __user *data; @@ -495,7 +532,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_LOAD_APP_REQ: { struct compat_qseecom_load_img_req __user *data32; struct qseecom_load_img_req __user *data; @@ -515,7 +552,7 @@ long compat_qseecom_ioctl(struct file *file, err = compat_put_qseecom_load_img_req(data32, data); return ret ? ret : err; } - + break; case COMPAT_QSEECOM_IOCTL_SEND_CMD_REQ: { struct compat_qseecom_send_cmd_req __user *data32; struct qseecom_send_cmd_req __user *data; @@ -533,7 +570,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: { struct compat_qseecom_send_modfd_cmd_req __user *data32; struct qseecom_send_modfd_cmd_req __user *data; @@ -551,7 +588,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_SET_MEM_PARAM_REQ: { struct compat_qseecom_set_sb_mem_param_req __user *data32; struct qseecom_set_sb_mem_param_req __user *data; @@ -569,7 +606,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ: { struct compat_qseecom_qseos_version_req __user *data32; struct qseecom_qseos_version_req __user *data; @@ -590,7 +627,7 @@ long compat_qseecom_ioctl(struct file *file, return ret ? ret : err; } - + break; case COMPAT_QSEECOM_IOCTL_SET_BUS_SCALING_REQ: { compat_int_t __user *data32; int __user *data; @@ -606,7 +643,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: { struct compat_qseecom_load_img_req __user *data32; struct qseecom_load_img_req __user *data; @@ -624,7 +661,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: { struct compat_qseecom_qseos_app_load_query __user *data32; struct qseecom_qseos_app_load_query __user *data; @@ -644,7 +681,7 @@ long compat_qseecom_ioctl(struct file *file, err = compat_put_qseecom_qseos_app_load_query(data32, data); return ret ? ret : err; } - + break; case COMPAT_QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: { struct compat_qseecom_send_svc_cmd_req __user *data32; struct qseecom_send_svc_cmd_req __user *data; @@ -662,7 +699,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_CREATE_KEY_REQ: { struct compat_qseecom_create_key_req __user *data32; struct qseecom_create_key_req __user *data; @@ -680,7 +717,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_WIPE_KEY_REQ: { struct compat_qseecom_wipe_key_req __user *data32; struct qseecom_wipe_key_req __user *data; @@ -698,7 +735,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ: { struct compat_qseecom_update_key_userinfo_req __user *data32; struct qseecom_update_key_userinfo_req __user *data; @@ -716,7 +753,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: { struct compat_qseecom_save_partition_hash_req __user *data32; struct qseecom_save_partition_hash_req __user *data; @@ -734,7 +771,7 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - + break; case COMPAT_QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: { struct compat_qseecom_is_es_activated_req __user *data32; struct qseecom_is_es_activated_req __user *data; @@ -754,7 +791,7 @@ long compat_qseecom_ioctl(struct file *file, err = compat_put_qseecom_is_es_activated_req(data32, data); return ret ? ret : err; } - + break; case COMPAT_QSEECOM_IOCTL_SEND_MODFD_RESP: { struct compat_qseecom_send_modfd_listener_resp __user *data32; struct qseecom_send_modfd_listener_resp __user *data; @@ -772,10 +809,8 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } - - case COMPAT_QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: - case COMPAT_QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ: - case COMPAT_QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ: { + break; + case COMPAT_QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ: { struct compat_qseecom_qteec_req __user *data32; struct qseecom_qteec_req __user *data; int err; @@ -792,9 +827,30 @@ long compat_qseecom_ioctl(struct file *file, return qseecom_ioctl(file, convert_cmd(cmd), (unsigned long)data); } + break; + case COMPAT_QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: + case COMPAT_QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ: + case COMPAT_QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: { + struct compat_qseecom_qteec_modfd_req __user *data32; + struct qseecom_qteec_modfd_req __user *data; + int err; + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_qseecom_qteec_modfd_req(data32, data); + if (err) + return err; + + return qseecom_ioctl(file, convert_cmd(cmd), + (unsigned long)data); + } + break; default: return -ENOIOCTLCMD; + break; } return 0; } diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index e8dc6931fbd..381f39726c4 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -546,6 +546,59 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, kzfree(tzbuf); break; } + case QSEOS_TEE_OPEN_SESSION: { + struct qseecom_qteec_ireq *req; + req = (struct qseecom_qteec_ireq *)req_buf; + smc_id = TZ_APP_GPAPP_OPEN_SESSION_ID; + desc.arginfo = TZ_APP_GPAPP_OPEN_SESSION_ID_PARAM_ID; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + ret = scm_call2(smc_id, &desc); + break; + } + case QSEOS_TEE_INVOKE_COMMAND: { + struct qseecom_qteec_ireq *req; + req = (struct qseecom_qteec_ireq *)req_buf; + smc_id = TZ_APP_GPAPP_INVOKE_COMMAND_ID; + desc.arginfo = TZ_APP_GPAPP_INVOKE_COMMAND_ID_PARAM_ID; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + ret = scm_call2(smc_id, &desc); + break; + } + case QSEOS_TEE_CLOSE_SESSION: { + struct qseecom_qteec_ireq *req; + req = (struct qseecom_qteec_ireq *)req_buf; + smc_id = TZ_APP_GPAPP_CLOSE_SESSION_ID; + desc.arginfo = TZ_APP_GPAPP_CLOSE_SESSION_ID_PARAM_ID; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + ret = scm_call2(smc_id, &desc); + break; + } + case QSEOS_TEE_REQUEST_CANCELLATION: { + struct qseecom_qteec_ireq *req; + req = (struct qseecom_qteec_ireq *)req_buf; + smc_id = TZ_APP_GPAPP_REQUEST_CANCELLATION_ID; + desc.arginfo = + TZ_APP_GPAPP_REQUEST_CANCELLATION_ID_PARAM_ID; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + ret = scm_call2(smc_id, &desc); + break; + } default: { pr_err("qseos_cmd_id 0x%d is not supported by armv8 scm_call2.\n", qseos_cmd_id); @@ -2004,20 +2057,10 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, struct qseecom_send_modfd_listener_resp *lstnr_resp, - struct qseecom_dev_handle *data, bool qteec, - int i) { + struct qseecom_dev_handle *data, int i) { if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { - if (qteec) { - if ((req->cmd_req_len < (TWO * sizeof(uint32_t))) || - (req->ifd_data[i].cmd_buf_offset > - req->cmd_req_len - (TWO * sizeof(uint32_t)))) { - pr_err("Invalid offset (QTEEC req len) 0x%x\n", - req->ifd_data[i].cmd_buf_offset); - return -EINVAL; - } - } else { if ((req->cmd_req_len < sizeof(uint32_t)) || (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(uint32_t))) { @@ -2025,18 +2068,8 @@ int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, req->ifd_data[i].cmd_buf_offset); return -EINVAL; } - } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { - if (qteec) { - if ((lstnr_resp->resp_len < TWO * sizeof(uint32_t)) || - (lstnr_resp->ifd_data[i].cmd_buf_offset > - lstnr_resp->resp_len - TWO*sizeof(uint32_t))) { - pr_err("Invalid offset (QTEEC resp len) 0x%x\n", - lstnr_resp->ifd_data[i].cmd_buf_offset); - return -EINVAL; - } - } else { if ((lstnr_resp->resp_len < sizeof(uint32_t)) || (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(uint32_t))) { @@ -2045,13 +2078,12 @@ int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, return -EINVAL; } } - } return 0; } #define SG_ENTRY_SZ sizeof(struct qseecom_sg_entry) static int __qseecom_update_cmd_buf(void *msg, bool cleanup, - struct qseecom_dev_handle *data, bool qteec) + struct qseecom_dev_handle *data) { struct ion_handle *ihandle; char *field; @@ -2128,8 +2160,7 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, uint32_t *update; update = (uint32_t *) field; - if (__boundary_checks_offset(req, lstnr_resp, data, - qteec, i)) + if (__boundary_checks_offset(req, lstnr_resp, data, i)) goto err; if (cleanup) *update = 0; @@ -2137,8 +2168,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, *update = (uint32_t)sg_dma_address( sg_ptr->sgl); len += (uint32_t)sg->length; - if (qteec) - *(update + 1) = (uint32_t)sg->length; } else { struct qseecom_sg_entry *update; int j = 0; @@ -2236,13 +2265,13 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data, (uintptr_t)req.resp_buf); - ret = __qseecom_update_cmd_buf(&req, false, data, false); + ret = __qseecom_update_cmd_buf(&req, false, data); if (ret) return ret; ret = __qseecom_send_cmd(data, &send_cmd_req); if (ret) return ret; - ret = __qseecom_update_cmd_buf(&req, true, data, false); + ret = __qseecom_update_cmd_buf(&req, true, data); if (ret) return ret; @@ -3046,7 +3075,8 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, } resp.resp_buf_ptr = this_lstnr->sb_virt + (uintptr_t)(resp.resp_buf_ptr - this_lstnr->user_virt_sb_base); - __qseecom_update_cmd_buf(&resp, false, data, false); + + __qseecom_update_cmd_buf(&resp, false, data); qseecom.send_resp_flag = 1; wake_up_interruptible(&qseecom.send_resp_wq); return 0; @@ -4138,6 +4168,13 @@ static int qseecom_save_partition_hash(void __user *argp) static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, struct qseecom_qteec_req *req) { + if (!data || !data->client.ihandle) { + pr_err("Client or client handle is not initialized\n"); + return -EINVAL; + } + + if (data->type != QSEECOM_CLIENT_APP) + return -EFAULT; if (req->req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len & rsp_len\n"); @@ -4203,6 +4240,77 @@ static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, return 0; } +static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req, + struct qseecom_dev_handle *data, bool cleanup) +{ + struct ion_handle *ihandle; + int ret = 0; + int i = 0; + uint32_t *update; + struct sg_table *sg_ptr = NULL; + struct scatterlist *sg; + + if (req == NULL) { + pr_err("Invalid address\n"); + return -EINVAL; + } + for (i = 0; i < MAX_ION_FD; i++) { + if (req->ifd_data[i].fd > 0) { + ihandle = ion_import_dma_buf(qseecom.ion_clnt, + req->ifd_data[i].fd); + if (IS_ERR_OR_NULL(ihandle)) { + pr_err("Ion client can't retrieve the handle\n"); + return -ENOMEM; + } + if ((req->req_len < sizeof(uint32_t)) || + (req->ifd_data[i].cmd_buf_offset > + req->req_len - sizeof(uint32_t))) { + pr_err("Invalid offset/req len 0x%x/0x%x\n", + req->req_len, + req->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + update = (uint32_t *)((char *) req->req_ptr + + req->ifd_data[i].cmd_buf_offset); + } else { + continue; + } + /* Populate the cmd data structure with the phys_addr */ + sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle); + if (sg_ptr == NULL) { + pr_err("IOn client could not retrieve sg table\n"); + goto err; + } + sg = sg_ptr->sgl; + if ((sg_ptr->nents != 1) || (sg->length == 0)) { + pr_err("Num of scat entr (%d)or length(%d) invalid\n", + sg_ptr->nents, sg->length); + goto err; + } + if (cleanup) + *update = 0; + else + *update = (uint32_t)sg_dma_address(sg_ptr->sgl); + + if (cleanup) + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, sg->length, + ION_IOC_INV_CACHES); + else + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, sg->length, + ION_IOC_CLEAN_INV_CACHES); + /* Deallocate the handle */ + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); + } + return ret; +err: + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); + return -ENOMEM; +} + static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, struct qseecom_qteec_req *req, uint32_t cmd_id) { @@ -4211,11 +4319,6 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, int ret = 0; uint32_t reqd_len_sb_in = 0; - if (!data || !data->client.ihandle) { - pr_err("Client or client handle is not initialized\n"); - return -EINVAL; - } - ret = __qseecom_qteec_validate_msg(data, req); if (ret) return ret; @@ -4228,15 +4331,22 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, (uintptr_t)req->resp_ptr); ireq.resp_len = req->resp_len; + if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || + (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { + ret = __qseecom_update_qteec_req_buf( + (struct qseecom_qteec_modfd_req *)req, data, false); + if (ret) + return ret; + } reqd_len_sb_in = req->req_len + req->resp_len; msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, ION_IOC_CLEAN_INV_CACHES); - ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &ireq, - sizeof(ireq), - &resp, sizeof(resp)); + ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, + (const void *) &ireq, sizeof(ireq), + &resp, sizeof(resp)); if (ret) { pr_err("scm_call() failed with err: %d (app_id = %d)\n", ret, data->client.app_id); @@ -4259,21 +4369,31 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, data->client.sb_length, ION_IOC_INV_CACHES); + + if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || + (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { + ret = __qseecom_update_qteec_req_buf( + (struct qseecom_qteec_modfd_req *)req, data, true); + if (ret) + return ret; + } return 0; } static int qseecom_qteec_open_session(struct qseecom_dev_handle *data, void __user *argp) { - struct qseecom_qteec_req req; + struct qseecom_qteec_modfd_req req; int ret = 0; - ret = copy_from_user(&req, argp, sizeof(struct qseecom_qteec_req)); + ret = copy_from_user(&req, argp, + sizeof(struct qseecom_qteec_modfd_req)); if (ret) { pr_err("copy_from_user failed\n"); return ret; } - ret = __qseecom_qteec_issue_cmd(data, &req, QSEOS_TEE_OPEN_SESSION); + ret = __qseecom_qteec_issue_cmd(data, (struct qseecom_qteec_req *)&req, + QSEOS_TEE_OPEN_SESSION); return ret; } @@ -4296,7 +4416,7 @@ static int qseecom_qteec_close_session(struct qseecom_dev_handle *data, static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, void __user *argp) { - struct qseecom_send_modfd_cmd_req req; + struct qseecom_qteec_modfd_req req; struct qseecom_command_scm_resp resp; struct qseecom_qteec_ireq ireq; int ret = 0; @@ -4304,17 +4424,11 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, uint32_t reqd_len_sb_in = 0; ret = copy_from_user(&req, argp, - sizeof(struct qseecom_send_modfd_cmd_req)); + sizeof(struct qseecom_qteec_modfd_req)); if (ret) { pr_err("copy_from_user failed\n"); return ret; } - - if (!data || !data->client.ihandle) { - pr_err("Client or client handle is not initialized\n"); - return -EINVAL; - } - ret = __qseecom_qteec_validate_msg(data, (struct qseecom_qteec_req *)(&req)); if (ret) @@ -4323,34 +4437,35 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, ireq.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND; ireq.app_id = data->client.app_id; ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.cmd_req_buf); - ireq.req_len = req.cmd_req_len; + (uintptr_t)req.req_ptr); + ireq.req_len = req.req_len; ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.resp_buf); + (uintptr_t)req.resp_ptr); ireq.resp_len = req.resp_len; - reqd_len_sb_in = req.cmd_req_len + req.resp_len; + reqd_len_sb_in = req.req_len + req.resp_len; /* validate offsets */ for (i = 0; i < MAX_ION_FD; i++) { if (req.ifd_data[i].fd) { - if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) + if (req.ifd_data[i].cmd_buf_offset >= req.req_len) return -EINVAL; } } - req.cmd_req_buf = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.cmd_req_buf); - req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.resp_buf); - ret = __qseecom_update_cmd_buf(&req, false, data, true); + req.req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.req_ptr); + req.resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.resp_ptr); + ret = __qseecom_update_qteec_req_buf(&req, data, false); if (ret) return ret; msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, ION_IOC_CLEAN_INV_CACHES); - ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &ireq, - sizeof(ireq), - &resp, sizeof(resp)); + + ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, + (const void *) &ireq, sizeof(ireq), + &resp, sizeof(resp)); if (ret) { pr_err("scm_call() failed with err: %d (app_id = %d)\n", ret, data->client.app_id); @@ -4370,7 +4485,7 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, ret = -EINVAL; } } - ret = __qseecom_update_cmd_buf(&req, true, data, true); + ret = __qseecom_update_qteec_req_buf(&req, data, true); if (ret) return ret; @@ -4380,6 +4495,24 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, return 0; } +static int qseecom_qteec_request_cancellation(struct qseecom_dev_handle *data, + void __user *argp) +{ + struct qseecom_qteec_modfd_req req; + int ret = 0; + + ret = copy_from_user(&req, argp, + sizeof(struct qseecom_qteec_modfd_req)); + if (ret) { + pr_err("copy_from_user failed\n"); + return ret; + } + ret = __qseecom_qteec_issue_cmd(data, (struct qseecom_qteec_req *)&req, + QSEOS_TEE_REQUEST_CANCELLATION); + + return ret; +} + long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) { int ret = 0; @@ -4979,6 +5112,30 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) pr_err("failed Invoke cmd: %d\n", ret); break; } + case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: { + if ((data->client.app_id == 0) || + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("Cancel req: invalid handle (%d) appid(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } + if (qseecom.qsee_version < QSEE_VERSION_20) { + pr_err("GP feature unsupported: qsee ver %u\n", + qseecom.qsee_version); + return -EINVAL; + } + /* Only one client allowed here at a time */ + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); + ret = qseecom_qteec_request_cancellation(data, argp); + atomic_dec(&data->ioctl_count); + wake_up_all(&data->abort_wq); + mutex_unlock(&app_access_lock); + if (ret) + pr_err("failed request_cancellation: %d\n", ret); + break; + } default: pr_err("Invalid IOCTL: 0x%x\n", cmd); return -EINVAL; diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h index 1fcd12c2f81..f380509a628 100644 --- a/include/soc/qcom/qseecomi.h +++ b/include/soc/qcom/qseecomi.h @@ -58,7 +58,9 @@ enum qseecom_qceos_cmd_id { QSEOS_UPDATE_KEY_USERINFO, QSEOS_TEE_OPEN_SESSION, QSEOS_TEE_INVOKE_COMMAND, + QSEOS_TEE_INVOKE_MODFD_COMMAND = QSEOS_TEE_INVOKE_COMMAND, QSEOS_TEE_CLOSE_SESSION, + QSEOS_TEE_REQUEST_CANCELLATION, QSEOS_FSM_LTE_INIT_DB = 0x100, QSEOS_FSM_LTE_STORE_KENB = 0x101, QSEOS_FSM_LTE_GEN_KEYS = 0x102, @@ -514,4 +516,44 @@ __packed struct qseecom_client_send_fsm_key_req { TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ TZ_SYSCALL_PARAM_TYPE_VAL) +#define TZ_APP_GPAPP_OPEN_SESSION_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x02) + +#define TZ_APP_GPAPP_OPEN_SESSION_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_5( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_APP_GPAPP_CLOSE_SESSION_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x03) + +#define TZ_APP_GPAPP_CLOSE_SESSION_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_5( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_APP_GPAPP_INVOKE_COMMAND_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x04) + +#define TZ_APP_GPAPP_INVOKE_COMMAND_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_5( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_APP_GPAPP_REQUEST_CANCELLATION_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x05) + +#define TZ_APP_GPAPP_REQUEST_CANCELLATION_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_5( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + #endif /* __QSEECOMI_H_ */ diff --git a/include/uapi/linux/compat_qseecom.h b/include/uapi/linux/compat_qseecom.h index 1fde4340847..6c83852ee49 100644 --- a/include/uapi/linux/compat_qseecom.h +++ b/include/uapi/linux/compat_qseecom.h @@ -266,13 +266,16 @@ extern long compat_qseecom_ioctl(struct file *file, struct compat_qseecom_update_key_userinfo_req) #define COMPAT_QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ \ - _IOWR(QSEECOM_IOC_MAGIC, 30, struct compat_qseecom_qteec_req) + _IOWR(QSEECOM_IOC_MAGIC, 30, struct compat_qseecom_qteec_modfd_req) #define COMPAT_QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ \ _IOWR(QSEECOM_IOC_MAGIC, 31, struct compat_qseecom_qteec_req) #define COMPAT_QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ \ - _IOWR(QSEECOM_IOC_MAGIC, 32, struct compat_qseecom_qteec_req) + _IOWR(QSEECOM_IOC_MAGIC, 32, struct compat_qseecom_qteec_modfd_req) + +#define COMPAT_QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ \ + _IOWR(QSEECOM_IOC_MAGIC, 33, struct compat_qseecom_qteec_modfd_req) #endif #endif /* _UAPI_COMPAT_QSEECOM_H_ */ diff --git a/include/uapi/linux/qseecom.h b/include/uapi/linux/qseecom.h index 16bcab319e9..ed45c9fb5ed 100644 --- a/include/uapi/linux/qseecom.h +++ b/include/uapi/linux/qseecom.h @@ -280,12 +280,15 @@ extern long qseecom_ioctl(struct file *file, _IOWR(QSEECOM_IOC_MAGIC, 24, struct qseecom_update_key_userinfo_req) #define QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ \ - _IOWR(QSEECOM_IOC_MAGIC, 30, struct qseecom_qteec_req) + _IOWR(QSEECOM_IOC_MAGIC, 30, struct qseecom_qteec_modfd_req) #define QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ \ _IOWR(QSEECOM_IOC_MAGIC, 31, struct qseecom_qteec_req) #define QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ \ - _IOWR(QSEECOM_IOC_MAGIC, 32, struct qseecom_qteec_req) + _IOWR(QSEECOM_IOC_MAGIC, 32, struct qseecom_qteec_modfd_req) + +#define QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ \ + _IOWR(QSEECOM_IOC_MAGIC, 33, struct qseecom_qteec_modfd_req) #endif /* _UAPI_QSEECOM_H_ */