Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 995bb603 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qseecom: support whitelist memory for qseecom_send_modfd_cmd"

parents 054ae586 8d26e8ee
Loading
Loading
Loading
Loading
+326 −40
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ struct qseecom_control {
	uint32_t          qseos_version;
	uint32_t          qsee_version;
	struct device *pdev;
	bool  whitelist_support;
	bool  commonlib_loaded;
	bool  commonlib64_loaded;
	struct ion_handle *cmnlib_ion_handle;
@@ -267,6 +268,30 @@ struct qseecom_listener_handle {

static struct qseecom_control qseecom;

struct sglist_info {
	uint32_t indexAndFlags;
	uint32_t sizeOrCount;
};

/*
 * The 31th bit indicates only one or multiple physical address inside
 * the request buffer. If it is set,  the index locates a single physical addr
 * inside the request buffer, and `sizeOrCount` is the size of the memory being
 * shared at that physical address.
 * Otherwise, the index locates an array of {start, len} pairs (a
 * "scatter/gather list"), and `sizeOrCount` gives the number of entries in
 * that array.
 *
 * The 30th bit indicates 64 or 32bit address; when it is set, physical addr
 * and scatter gather entry sizes are 64-bit values.  Otherwise, 32-bit values.
 *
 * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer.
 */
#define SGLISTINFO_SET_INDEX_FLAG(c, s, i)	\
	((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff)))

#define SGLISTINFO_TABLE_SIZE	(sizeof(struct sglist_info) * MAX_ION_FD)

struct qseecom_dev_handle {
	enum qseecom_client_handle_type type;
	union {
@@ -280,6 +305,8 @@ struct qseecom_dev_handle {
	bool  perf_enabled;
	bool  fast_load_enabled;
	enum qseecom_bandwidth_request_mode mode;
	struct sglist_info *sglistinfo_ptr;
	uint32_t sglist_cnt;
};

struct qseecom_key_id_usage_desc {
@@ -612,6 +639,38 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: {
			struct qseecom_client_send_data_ireq *req;
			struct qseecom_client_send_data_64bit_ireq *req_64bit;

			smc_id = TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID;
			desc.arginfo =
			TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID;
			if (qseecom.qsee_version < QSEE_VERSION_40) {
				req = (struct qseecom_client_send_data_ireq *)
					req_buf;
				desc.args[0] = req->app_id;
				desc.args[1] = req->req_ptr;
				desc.args[2] = req->req_len;
				desc.args[3] = req->rsp_ptr;
				desc.args[4] = req->rsp_len;
				desc.args[5] = req->sglistinfo_ptr;
				desc.args[6] = req->sglistinfo_len;
			} else {
				req_64bit =
				(struct qseecom_client_send_data_64bit_ireq *)
					req_buf;
				desc.args[0] = req_64bit->app_id;
				desc.args[1] = req_64bit->req_ptr;
				desc.args[2] = req_64bit->req_len;
				desc.args[3] = req_64bit->rsp_ptr;
				desc.args[4] = req_64bit->rsp_len;
				desc.args[5] = req_64bit->sglistinfo_ptr;
				desc.args[6] = req_64bit->sglistinfo_len;
			}
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_RPMB_PROVISION_KEY_COMMAND: {
			struct qseecom_client_send_service_ireq *req;
			req = (struct qseecom_client_send_service_ireq *)
@@ -754,6 +813,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_TEE_OPEN_SESSION_WHITELIST: {
			struct qseecom_qteec_ireq *req;
			struct qseecom_qteec_64bit_ireq *req_64bit;

			smc_id = TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID;
			desc.arginfo =
			TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID;
			if (qseecom.qsee_version < QSEE_VERSION_40) {
				req = (struct qseecom_qteec_ireq *)req_buf;
				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;
				desc.args[5] = req->sglistinfo_ptr;
				desc.args[6] = req->sglistinfo_len;
			} else {
				req_64bit = (struct qseecom_qteec_64bit_ireq *)
						req_buf;
				desc.args[0] = req_64bit->app_id;
				desc.args[1] = req_64bit->req_ptr;
				desc.args[2] = req_64bit->req_len;
				desc.args[3] = req_64bit->resp_ptr;
				desc.args[4] = req_64bit->resp_len;
				desc.args[5] = req_64bit->sglistinfo_ptr;
				desc.args[6] = req_64bit->sglistinfo_len;
			}
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_TEE_INVOKE_COMMAND: {
			struct qseecom_qteec_ireq *req;
			struct qseecom_qteec_64bit_ireq *req_64bit;
@@ -778,6 +867,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: {
			struct qseecom_qteec_ireq *req;
			struct qseecom_qteec_64bit_ireq *req_64bit;

			smc_id = TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID;
			desc.arginfo =
			TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID;
			if (qseecom.qsee_version < QSEE_VERSION_40) {
				req = (struct qseecom_qteec_ireq *)req_buf;
				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;
				desc.args[5] = req->sglistinfo_ptr;
				desc.args[6] = req->sglistinfo_len;
			} else {
				req_64bit = (struct qseecom_qteec_64bit_ireq *)
						req_buf;
				desc.args[0] = req_64bit->app_id;
				desc.args[1] = req_64bit->req_ptr;
				desc.args[2] = req_64bit->req_len;
				desc.args[3] = req_64bit->resp_ptr;
				desc.args[4] = req_64bit->resp_len;
				desc.args[5] = req_64bit->sglistinfo_ptr;
				desc.args[6] = req_64bit->sglistinfo_len;
			}
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_TEE_CLOSE_SESSION: {
			struct qseecom_qteec_ireq *req;
			struct qseecom_qteec_64bit_ireq *req_64bit;
@@ -2705,14 +2824,15 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
{
	int ret = 0;
	u32 reqd_len_sb_in = 0;
	struct qseecom_client_send_data_ireq send_data_req;
	struct qseecom_client_send_data_64bit_ireq send_data_req_64bit;
	struct qseecom_client_send_data_ireq send_data_req = {0};
	struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0};
	struct qseecom_command_scm_resp resp;
	unsigned long flags;
	struct qseecom_registered_app_list *ptr_app;
	bool found_app = false;
	void *cmd_buf = NULL;
	size_t cmd_len;
	struct sglist_info *table = data->sglistinfo_ptr;

	reqd_len_sb_in = req->cmd_req_len + req->resp_len;
	/* find app_id & img_name from list */
@@ -2734,7 +2854,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
	}

	if (qseecom.qsee_version < QSEE_VERSION_40) {
		send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
		send_data_req.app_id = data->client.app_id;
		send_data_req.req_ptr = (uint32_t)(__qseecom_uvirt_to_kphys(
					data, (uintptr_t)req->cmd_req_buf));
@@ -2742,11 +2861,14 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
		send_data_req.rsp_ptr = (uint32_t)(__qseecom_uvirt_to_kphys(
					data, (uintptr_t)req->resp_buf));
		send_data_req.rsp_len = req->resp_len;
		send_data_req.sglistinfo_ptr =
				(uint32_t)virt_to_phys(table);
		send_data_req.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
		cmd_buf = (void *)&send_data_req;
		cmd_len = sizeof(struct qseecom_client_send_data_ireq);
	} else {
		send_data_req_64bit.qsee_cmd_id =
					QSEOS_CLIENT_SEND_DATA_COMMAND;
		send_data_req_64bit.app_id = data->client.app_id;
		send_data_req_64bit.req_ptr = __qseecom_uvirt_to_kphys(data,
					(uintptr_t)req->cmd_req_buf);
@@ -2768,10 +2890,20 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
				send_data_req_64bit.rsp_len);
			return -EFAULT;
		}
		send_data_req_64bit.sglistinfo_ptr =
				(uint64_t)virt_to_phys(table);
		send_data_req_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
		cmd_buf = (void *)&send_data_req_64bit;
		cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq);
	}

	if (qseecom.whitelist_support == false)
		*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND;
	else
		*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;

	msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
					data->client.sb_virt,
					reqd_len_sb_in,
@@ -3025,14 +3157,26 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
					goto err;
			}
		}
		if (cleanup)

		if (cleanup) {
			msm_ion_do_cache_op(qseecom.ion_clnt,
					ihandle, NULL, len,
					ION_IOC_INV_CACHES);
		else
		} else {
			msm_ion_do_cache_op(qseecom.ion_clnt,
					ihandle, NULL, len,
					ION_IOC_CLEAN_INV_CACHES);
			if (data->type == QSEECOM_CLIENT_APP) {
				data->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 0,
					req->ifd_data[i].cmd_buf_offset);
				data->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				data->sglist_cnt = i + 1;
			}
		}
		/* Deallocate the handle */
		if (!IS_ERR_OR_NULL(ihandle))
			ion_free(qseecom.ion_clnt, ihandle);
@@ -3231,14 +3375,25 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
			}
		}
cleanup:
		if (cleanup)
		if (cleanup) {
			msm_ion_do_cache_op(qseecom.ion_clnt,
					ihandle, NULL, len,
					ION_IOC_INV_CACHES);
		else
		} else {
			msm_ion_do_cache_op(qseecom.ion_clnt,
					ihandle, NULL, len,
					ION_IOC_CLEAN_INV_CACHES);
			if (data->type == QSEECOM_CLIENT_APP) {
				data->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 1,
					req->ifd_data[i].cmd_buf_offset);
				data->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				data->sglist_cnt = i + 1;
			}
		}
		/* Deallocate the handle */
		if (!IS_ERR_OR_NULL(ihandle))
			ion_free(qseecom.ion_clnt, ihandle);
@@ -5897,14 +6052,23 @@ static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req,
				*update = (uint32_t)sg_dma_address(sg_ptr->sgl);
		}
clean:
		if (cleanup)
		if (cleanup) {
			msm_ion_do_cache_op(qseecom.ion_clnt,
				ihandle, NULL, sg->length,
				ION_IOC_INV_CACHES);
		else
		} else {
			msm_ion_do_cache_op(qseecom.ion_clnt,
				ihandle, NULL, sg->length,
				ION_IOC_CLEAN_INV_CACHES);
			data->sglistinfo_ptr[i].indexAndFlags =
				SGLISTINFO_SET_INDEX_FLAG(
				(sg_ptr->nents == 1), 0,
				req->ifd_data[i].cmd_buf_offset);
			data->sglistinfo_ptr[i].sizeOrCount =
				(sg_ptr->nents == 1) ?
				sg->length : sg_ptr->nents;
			data->sglist_cnt = i + 1;
		}
		/* Deallocate the handle */
		if (!IS_ERR_OR_NULL(ihandle))
			ion_free(qseecom.ion_clnt, ihandle);
@@ -5929,6 +6093,7 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
	uint32_t reqd_len_sb_in = 0;
	void *cmd_buf = NULL;
	size_t cmd_len;
	struct sglist_info *table = data->sglistinfo_ptr;

	ret  = __qseecom_qteec_validate_msg(data, req);
	if (ret)
@@ -5951,8 +6116,15 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
		return -ENOENT;
	}

	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;
	}

	if (qseecom.qsee_version < QSEE_VERSION_40) {
		ireq.qsee_cmd_id = cmd_id;
		ireq.app_id = data->client.app_id;
		ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req->req_ptr);
@@ -5960,10 +6132,13 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
		ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req->resp_ptr);
		ireq.resp_len = req->resp_len;
		ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table);
		ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
		cmd_buf = (void *)&ireq;
		cmd_len = sizeof(struct qseecom_qteec_ireq);
	} else {
		ireq_64bit.qsee_cmd_id = cmd_id;
		ireq_64bit.app_id = data->client.app_id;
		ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req->req_ptr);
@@ -5983,17 +6158,19 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
				ireq_64bit.resp_ptr, ireq_64bit.resp_len);
			return -EFAULT;
		}
		ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table);
		ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
		cmd_buf = (void *)&ireq_64bit;
		cmd_len = sizeof(struct qseecom_qteec_64bit_ireq);
	}
	if (qseecom.whitelist_support == true
		&& cmd_id == QSEOS_TEE_OPEN_SESSION)
		*(uint32_t *)cmd_buf = QSEOS_TEE_OPEN_SESSION_WHITELIST;
	else
		*(uint32_t *)cmd_buf = cmd_id;

	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,
@@ -6091,6 +6268,9 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
	uint32_t reqd_len_sb_in = 0;
	void *cmd_buf = NULL;
	size_t cmd_len;
	struct sglist_info *table = data->sglistinfo_ptr;
	void *req_ptr = NULL;
	void *resp_ptr = NULL;

	ret = copy_from_user(&req, argp,
			sizeof(struct qseecom_qteec_modfd_req));
@@ -6102,6 +6282,8 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
					(struct qseecom_qteec_req *)(&req));
	if (ret)
		return ret;
	req_ptr = req.req_ptr;
	resp_ptr = req.resp_ptr;

	/* find app_id & img_name from list */
	spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
@@ -6120,45 +6302,56 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
		return -ENOENT;
	}

	/* 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.req_len)
				return -EINVAL;
		}
	}
	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;

	if (qseecom.qsee_version < QSEE_VERSION_40) {
		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.req_ptr);
						(uintptr_t)req_ptr);
		ireq.req_len = req.req_len;
		ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req.resp_ptr);
						(uintptr_t)resp_ptr);
		ireq.resp_len = req.resp_len;
		cmd_buf = (void *)&ireq;
		cmd_len = sizeof(struct qseecom_qteec_ireq);
		ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table);
		ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
	} else {
		ireq_64bit.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND;
		ireq_64bit.app_id = data->client.app_id;
		ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req.req_ptr);
						(uintptr_t)req_ptr);
		ireq_64bit.req_len = req.req_len;
		ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
						(uintptr_t)req.resp_ptr);
						(uintptr_t)resp_ptr);
		ireq_64bit.resp_len = req.resp_len;
		cmd_buf = (void *)&ireq_64bit;
		cmd_len = sizeof(struct qseecom_qteec_64bit_ireq);
		ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table);
		ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
		dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
	}
	reqd_len_sb_in = req.req_len + req.resp_len;
	if (qseecom.whitelist_support == true)
		*(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND_WHITELIST;
	else
		*(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND;

	/* 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.req_len)
				return -EINVAL;
		}
	}
	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,
@@ -6221,6 +6414,15 @@ static int qseecom_qteec_request_cancellation(struct qseecom_dev_handle *data,
	return ret;
}

static void __qseecom_clean_data_sglistinfo(struct qseecom_dev_handle *data)
{
	if (data->sglist_cnt) {
		memset(data->sglistinfo_ptr, 0,
			SGLISTINFO_TABLE_SIZE);
		data->sglist_cnt = 0;
	}
}

long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
	int ret = 0;
@@ -6400,6 +6602,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
		mutex_unlock(&app_access_lock);
		if (ret)
			pr_err("failed qseecom_send_cmd: %d\n", ret);
		__qseecom_clean_data_sglistinfo(data);
		break;
	}
	case QSEECOM_IOCTL_RECEIVE_REQ: {
@@ -6797,6 +7000,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
		mutex_unlock(&app_access_lock);
		if (ret)
			pr_err("failed open_session_cmd: %d\n", ret);
		__qseecom_clean_data_sglistinfo(data);
		break;
	}
	case QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ: {
@@ -6845,6 +7049,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
		mutex_unlock(&app_access_lock);
		if (ret)
			pr_err("failed Invoke cmd: %d\n", ret);
		__qseecom_clean_data_sglistinfo(data);
		break;
	}
	case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: {
@@ -6921,6 +7126,9 @@ static int qseecom_open(struct inode *inode, struct file *file)
	init_waitqueue_head(&data->abort_wq);
	atomic_set(&data->ioctl_count, 0);

	data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL);
	if (!(data->sglistinfo_ptr))
		return -ENOMEM;
	return ret;
}

@@ -6975,6 +7183,7 @@ static int qseecom_release(struct inode *inode, struct file *file)
		if (data->perf_enabled == true)
			qsee_disable_clock_vote(data, CLK_DFAB);
	}
	kfree(data->sglistinfo_ptr);
	kfree(data);

	return ret;
@@ -7722,6 +7931,74 @@ out:
	return ret;
}

/*
 * Check if whitelist feature is supported by making a test scm_call
 * to send a whitelist command to an invalid app ID 0
 */
static int qseecom_check_whitelist_feature(void)
{
	struct qseecom_client_send_data_ireq send_data_req = {0};
	struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0};
	struct qseecom_command_scm_resp resp;
	uint32_t buf_size = 128;
	void *buf = NULL;
	void *cmd_buf = NULL;
	size_t cmd_len;
	int ret = 0;
	phys_addr_t pa;

	buf = kzalloc(buf_size, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;
	pa = virt_to_phys(buf);
	if (qseecom.qsee_version < QSEE_VERSION_40) {
		send_data_req.qsee_cmd_id =
			QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
		send_data_req.app_id = 0;
		send_data_req.req_ptr = (uint32_t)pa;
		send_data_req.req_len = buf_size;
		send_data_req.rsp_ptr = (uint32_t)pa;
		send_data_req.rsp_len = buf_size;
		send_data_req.sglistinfo_ptr = (uint32_t)pa;
		send_data_req.sglistinfo_len = buf_size;
		cmd_buf = (void *)&send_data_req;
		cmd_len = sizeof(struct qseecom_client_send_data_ireq);
	} else {
		send_data_req_64bit.qsee_cmd_id =
			QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
		send_data_req_64bit.app_id = 0;
		send_data_req_64bit.req_ptr = (uint64_t)pa;
		send_data_req_64bit.req_len = buf_size;
		send_data_req_64bit.rsp_ptr = (uint64_t)pa;
		send_data_req_64bit.rsp_len = buf_size;
		send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa;
		send_data_req_64bit.sglistinfo_len = buf_size;
		cmd_buf = (void *)&send_data_req_64bit;
		cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq);
	}
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
				cmd_buf, cmd_len,
				&resp, sizeof(resp));
/*
 * If this cmd exists and whitelist is supported, scm_call return -2 (scm
 * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise,
 * scm_call return -1 (remap to -EIO).
 */
	if (ret == -EIO) {
		qseecom.whitelist_support = false;
		ret = 0;
	} else if (ret == -EINVAL &&
		resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) {
		qseecom.whitelist_support = true;
		ret = 0;
	} else {
		pr_err("Failed to check whitelist: ret = %d, result = 0x%x\n",
			ret, resp.result);
	}
	kfree(buf);
	return ret;
}

static int qseecom_probe(struct platform_device *pdev)
{
	int rc;
@@ -7754,6 +8031,7 @@ static int qseecom_probe(struct platform_device *pdev)

	qseecom.app_block_ref_cnt = 0;
	init_waitqueue_head(&qseecom.app_block_wq);
	qseecom.whitelist_support = true;

	rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
	if (rc < 0) {
@@ -7969,6 +8247,14 @@ static int qseecom_probe(struct platform_device *pdev)
	qseecom.qsee_perf_client = msm_bus_scale_register_client(
					qseecom_platform_support);

	rc = qseecom_check_whitelist_feature();
	if (rc) {
		rc = -EINVAL;
		goto exit_destroy_ion_client;
	}
	pr_warn("qseecom.whitelist_support = %d\n",
				qseecom.whitelist_support);

	if (!qseecom.qsee_perf_client)
		pr_err("Unable to register bus client\n");

+46 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2016, The Linux Foundation. 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 and
@@ -18,6 +18,7 @@

#define QSEECOM_KEY_ID_SIZE   32

#define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD  -19   /*0xFFFFFFED*/
#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
#define QSEOS_RESULT_FAIL_KS_OP               -64
#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65
@@ -64,6 +65,9 @@ enum qseecom_qceos_cmd_id {
	QSEOS_TEE_REQUEST_CANCELLATION,
	QSEOS_CONTINUE_BLOCKED_REQ_COMMAND,
	QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND = 0x1B,
	QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C,
	QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D,
	QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E,
	QSEOS_FSM_LTEOTA_REQ_CMD = 0x109,
	QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110,
	QSEOS_FSM_IKE_REQ_CMD = 0x203,
@@ -181,6 +185,8 @@ __packed struct qseecom_client_send_data_ireq {
	uint32_t req_len;
	uint32_t rsp_ptr;/* First 4 bytes should be the return status */
	uint32_t rsp_len;
	uint32_t sglistinfo_ptr;
	uint32_t sglistinfo_len;
};

__packed struct qseecom_client_send_data_64bit_ireq {
@@ -190,6 +196,8 @@ __packed struct qseecom_client_send_data_64bit_ireq {
	uint32_t req_len;
	uint64_t rsp_ptr;
	uint32_t rsp_len;
	uint64_t sglistinfo_ptr;
	uint32_t sglistinfo_len;
};

__packed struct qseecom_reg_log_buf_ireq {
@@ -292,6 +300,8 @@ __packed struct qseecom_qteec_ireq {
	uint32_t    req_len;
	uint32_t    resp_ptr;
	uint32_t    resp_len;
	uint32_t    sglistinfo_ptr;
	uint32_t    sglistinfo_len;
};

__packed struct qseecom_qteec_64bit_ireq {
@@ -301,6 +311,8 @@ __packed struct qseecom_qteec_64bit_ireq {
	uint32_t    req_len;
	uint64_t    resp_ptr;
	uint32_t    resp_len;
	uint64_t    sglistinfo_ptr;
	uint32_t    sglistinfo_len;
};

__packed struct qseecom_client_send_fsm_key_req {
@@ -658,4 +670,37 @@ __packed struct qseecom_continue_blocked_request_ireq {
#define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID \
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \
	TZ_SVC_APP_ID_PLACEHOLDER, 0x06)

#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_7( \
	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, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
	TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID			\
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS,			\
	TZ_SVC_APP_ID_PLACEHOLDER, 0x07)

#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID		\
	TZ_SYSCALL_CREATE_PARAM_ID_7(					\
	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, TZ_SYSCALL_PARAM_TYPE_BUF_RW,	\
	TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID			\
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS,			\
	TZ_SVC_APP_ID_PLACEHOLDER, 0x09)

#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID		\
	TZ_SYSCALL_CREATE_PARAM_ID_7(					\
	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, TZ_SYSCALL_PARAM_TYPE_BUF_RW,	\
	TZ_SYSCALL_PARAM_TYPE_VAL)

#endif /* __QSEECOMI_H_ */