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

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

Merge "qseecom: whitelist support for kernel client and listener"

parents ef6c4f46 9bd39866
Loading
Loading
Loading
Loading
+187 −135
Original line number Diff line number Diff line
@@ -131,6 +131,35 @@ static DEFINE_MUTEX(qsee_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
static DEFINE_MUTEX(clk_access_lock);

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)

#define FEATURE_ID_WHITELIST	15	/*whitelist feature id*/

#define MAKE_WHITELIST_VERSION(major, minor, patch) \
	(((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))

struct qseecom_registered_listener_list {
	struct list_head                 list;
	struct qseecom_register_listener_req svc;
@@ -145,6 +174,8 @@ struct qseecom_registered_listener_list {
	bool                       listener_in_use;
	/* wq for thread blocked on this listener*/
	wait_queue_head_t          listener_block_app_wq;
	struct sglist_info sglistinfo_ptr[MAX_ION_FD];
	uint32_t sglist_cnt;
};

struct qseecom_registered_app_list {
@@ -268,30 +299,6 @@ 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 {
@@ -305,8 +312,9 @@ struct qseecom_dev_handle {
	bool  perf_enabled;
	bool  fast_load_enabled;
	enum qseecom_bandwidth_request_mode mode;
	struct sglist_info *sglistinfo_ptr;
	struct sglist_info sglistinfo_ptr[MAX_ION_FD];
	uint32_t sglist_cnt;
	bool use_legacy_cmd;
};

struct qseecom_key_id_usage_desc {
@@ -584,6 +592,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: {
			struct qseecom_client_listener_data_irsp *req;
			struct qseecom_client_listener_data_64bit_irsp *req_64;

			smc_id =
			TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID;
			desc.arginfo =
			TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID;
			if (qseecom.qsee_version < QSEE_VERSION_40) {
				req =
				(struct qseecom_client_listener_data_irsp *)
				req_buf;
				desc.args[0] = req->listener_id;
				desc.args[1] = req->status;
				desc.args[2] = req->sglistinfo_ptr;
				desc.args[3] = req->sglistinfo_len;
			} else {
				req_64 =
			(struct qseecom_client_listener_data_64bit_irsp *)
				req_buf;
				desc.args[0] = req_64->listener_id;
				desc.args[1] = req_64->status;
				desc.args[2] = req_64->sglistinfo_ptr;
				desc.args[3] = req_64->sglistinfo_len;
			}
			ret = scm_call2(smc_id, &desc);
			break;
		}
		case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: {
			struct qseecom_load_app_ireq *req;
			struct qseecom_load_app_64bit_ireq *req_64bit;
@@ -1128,7 +1164,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
		return -EBUSY;
	}

	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
	if (!new_entry) {
		pr_err("kmalloc failed\n");
		return -ENOMEM;
@@ -1593,6 +1629,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data,
	return ret;
}

static void __qseecom_clean_listener_sglistinfo(
			struct qseecom_registered_listener_list *ptr_svc)
{
	if (ptr_svc->sglist_cnt) {
		memset(ptr_svc->sglistinfo_ptr, 0,
			SGLISTINFO_TABLE_SIZE);
		ptr_svc->sglist_cnt = 0;
	}
}

static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
					struct qseecom_command_scm_resp *resp)
{
@@ -1601,9 +1647,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
	uint32_t lstnr;
	unsigned long flags;
	struct qseecom_client_listener_data_irsp send_data_rsp;
	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
	struct qseecom_registered_listener_list *ptr_svc = NULL;
	sigset_t new_sigset;
	sigset_t old_sigset;
	uint32_t status;
	void *cmd_buf = NULL;
	size_t cmd_len;
	struct sglist_info *table = NULL;

	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
		lstnr = resp->data;
@@ -1677,15 +1728,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
				data->client.app_id, lstnr, ret);
			rc = -ENODEV;
			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
			status = QSEOS_RESULT_FAILURE;
		} else {
			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
			status = QSEOS_RESULT_SUCCESS;
		}

		qseecom.send_resp_flag = 0;
		ptr_svc->send_resp_flag = 0;
		send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
		table = ptr_svc->sglistinfo_ptr;
		if (qseecom.qsee_version < QSEE_VERSION_40) {
			send_data_rsp.listener_id  = lstnr;
			send_data_rsp.status = status;
			send_data_rsp.sglistinfo_ptr =
				(uint32_t)virt_to_phys(table);
			send_data_rsp.sglistinfo_len =
				SGLISTINFO_TABLE_SIZE;
			dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
			cmd_buf = (void *)&send_data_rsp;
			cmd_len = sizeof(send_data_rsp);
		} else {
			send_data_rsp_64bit.listener_id  = lstnr;
			send_data_rsp_64bit.status = status;
			send_data_rsp_64bit.sglistinfo_ptr =
				virt_to_phys(table);
			send_data_rsp_64bit.sglistinfo_len =
				SGLISTINFO_TABLE_SIZE;
			dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
			cmd_buf = (void *)&send_data_rsp_64bit;
			cmd_len = sizeof(send_data_rsp_64bit);
		}
		if (qseecom.whitelist_support == false)
			*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
		else
			*(uint32_t *)cmd_buf =
				QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
		if (ptr_svc)
			msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
					ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -1695,10 +1773,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
			__qseecom_enable_clk(CLK_QSEE);

		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
					(const void *)&send_data_rsp,
					sizeof(send_data_rsp), resp,
					sizeof(*resp));
					cmd_buf, cmd_len, resp, sizeof(*resp));
		ptr_svc->listener_in_use = false;
		__qseecom_clean_listener_sglistinfo(ptr_svc);
		if (ret) {
			pr_err("scm_call() failed with err: %d (app_id = %d)\n",
				ret, data->client.app_id);
@@ -1826,9 +1903,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
	uint32_t lstnr = 0;
	unsigned long flags;
	struct qseecom_client_listener_data_irsp send_data_rsp;
	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
	struct qseecom_registered_listener_list *ptr_svc = NULL;
	sigset_t new_sigset;
	sigset_t old_sigset;
	uint32_t status;
	void *cmd_buf = NULL;
	size_t cmd_len;
	struct sglist_info *table = NULL;

	while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
		lstnr = resp->data;
@@ -1891,13 +1973,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
				data->client.app_id, lstnr, ret);
			rc = -ENODEV;
			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
			status  = QSEOS_RESULT_FAILURE;
		} else {
			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
			status  = QSEOS_RESULT_SUCCESS;
		}

		send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
		table = ptr_svc->sglistinfo_ptr;
		if (qseecom.qsee_version < QSEE_VERSION_40) {
			send_data_rsp.listener_id  = lstnr;
			send_data_rsp.status = status;
			send_data_rsp.sglistinfo_ptr =
				(uint32_t)virt_to_phys(table);
			send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
			dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
			cmd_buf = (void *)&send_data_rsp;
			cmd_len = sizeof(send_data_rsp);
		} else {
			send_data_rsp_64bit.listener_id  = lstnr;
			send_data_rsp_64bit.status = status;
			send_data_rsp_64bit.sglistinfo_ptr =
				virt_to_phys(table);
			send_data_rsp_64bit.sglistinfo_len =
				SGLISTINFO_TABLE_SIZE;
			dmac_flush_range((void *)table,
				(void *)table + SGLISTINFO_TABLE_SIZE);
			cmd_buf = (void *)&send_data_rsp_64bit;
			cmd_len = sizeof(send_data_rsp_64bit);
		}
		if (qseecom.whitelist_support == false)
			*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
		else
			*(uint32_t *)cmd_buf =
				QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
		if (ptr_svc)
			msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
					ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -1907,11 +2014,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
			__qseecom_enable_clk(CLK_QSEE);

		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
					(const void *)&send_data_rsp,
					sizeof(send_data_rsp), resp,
					sizeof(*resp));

					cmd_buf, cmd_len, resp, sizeof(*resp));
		ptr_svc->listener_in_use = false;
		__qseecom_clean_listener_sglistinfo(ptr_svc);
		wake_up_interruptible(&ptr_svc->listener_block_app_wq);

		if (ret) {
@@ -2909,7 +3014,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
		cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq);
	}

	if (qseecom.whitelist_support == false)
	if (qseecom.whitelist_support == false || data->use_legacy_cmd == true)
		*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND;
	else
		*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
@@ -3014,6 +3119,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
	struct qseecom_send_modfd_cmd_req *req = NULL;
	struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL;
	struct qseecom_registered_listener_list *this_lstnr = NULL;
	uint32_t offset;
	struct sg_table *sg_ptr;

	if ((data->type != QSEECOM_LISTENER_SERVICE) &&
			(data->type != QSEECOM_CLIENT_APP))
@@ -3035,7 +3142,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
	}

	for (i = 0; i < MAX_ION_FD; i++) {
		struct sg_table *sg_ptr = NULL;
		if ((data->type != QSEECOM_LISTENER_SERVICE) &&
						(req->ifd_data[i].fd > 0)) {
			ihandle = ion_import_dma_buf(qseecom.ion_clnt,
@@ -3177,14 +3283,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
					ihandle, NULL, len,
					ION_IOC_CLEAN_INV_CACHES);
			if (data->type == QSEECOM_CLIENT_APP) {
				offset = req->ifd_data[i].cmd_buf_offset;
				data->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 0,
					req->ifd_data[i].cmd_buf_offset);
					(sg_ptr->nents == 1), 0, offset);
				data->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				data->sglist_cnt = i + 1;
			} else {
				offset = (lstnr_resp->ifd_data[i].cmd_buf_offset
					+ (uintptr_t)lstnr_resp->resp_buf_ptr -
					(uintptr_t)this_lstnr->sb_virt);
				this_lstnr->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 0, offset);
				this_lstnr->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				this_lstnr->sglist_cnt = i + 1;
			}
		}
		/* Deallocate the handle */
@@ -3257,6 +3374,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
	struct qseecom_send_modfd_cmd_req *req = NULL;
	struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL;
	struct qseecom_registered_listener_list *this_lstnr = NULL;
	uint32_t offset;
	struct sg_table *sg_ptr;

	if ((data->type != QSEECOM_LISTENER_SERVICE) &&
			(data->type != QSEECOM_CLIENT_APP))
@@ -3278,7 +3397,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
	}

	for (i = 0; i < MAX_ION_FD; i++) {
		struct sg_table *sg_ptr = NULL;
		if ((data->type != QSEECOM_LISTENER_SERVICE) &&
						(req->ifd_data[i].fd > 0)) {
			ihandle = ion_import_dma_buf(qseecom.ion_clnt,
@@ -3395,14 +3513,25 @@ cleanup:
					ihandle, NULL, len,
					ION_IOC_CLEAN_INV_CACHES);
			if (data->type == QSEECOM_CLIENT_APP) {
				offset = req->ifd_data[i].cmd_buf_offset;
				data->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 1,
					req->ifd_data[i].cmd_buf_offset);
					(sg_ptr->nents == 1), 1, offset);
				data->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				data->sglist_cnt = i + 1;
			} else {
				offset = (lstnr_resp->ifd_data[i].cmd_buf_offset
					+ (uintptr_t)lstnr_resp->resp_buf_ptr -
					(uintptr_t)this_lstnr->sb_virt);
				this_lstnr->sglistinfo_ptr[i].indexAndFlags =
					SGLISTINFO_SET_INDEX_FLAG(
					(sg_ptr->nents == 1), 1, offset);
				this_lstnr->sglistinfo_ptr[i].sizeOrCount =
					(sg_ptr->nents == 1) ?
					sg->length : sg_ptr->nents;
				this_lstnr->sglist_cnt = i + 1;
			}
		}
		/* Deallocate the handle */
@@ -4121,21 +4250,12 @@ int qseecom_start_app(struct qseecom_handle **handle,
	data->client.user_virt_sb_base = 0;
	data->client.ihandle = NULL;

	/* Allocate sglistinfo buffer for kernel client */
	data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL);
	if (!(data->sglistinfo_ptr)) {
		kfree(data);
		kfree(*handle);
		*handle = NULL;
		return -ENOMEM;
	}
	init_waitqueue_head(&data->abort_wq);

	data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096,
				ION_HEAP(ION_QSECOM_HEAP_ID), 0);
	if (IS_ERR_OR_NULL(data->client.ihandle)) {
		pr_err("Ion client could not retrieve the handle\n");
		kfree(data->sglistinfo_ptr);
		kfree(data);
		kfree(*handle);
		*handle = NULL;
@@ -4238,7 +4358,6 @@ int qseecom_start_app(struct qseecom_handle **handle,
	return 0;

err:
	kfree(data->sglistinfo_ptr);
	kfree(data);
	kfree(*handle);
	*handle = NULL;
@@ -4286,7 +4405,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle)

	mutex_unlock(&app_access_lock);
	if (ret == 0) {
		kzfree(data->sglistinfo_ptr);
		kzfree(data);
		kzfree(*handle);
		kzfree(kclient);
@@ -4352,8 +4470,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
		}
		perf_enabled = true;
	}
	if (!strcmp(data->client.app_name, "securemm"))
		data->use_legacy_cmd = true;

	ret = __qseecom_send_cmd(data, &req);
	data->use_legacy_cmd = false;
	if (qseecom.support_bus_scaling)
		__qseecom_add_bw_scale_down_timer(
			QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
@@ -7025,6 +7146,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
		wake_up_all(&data->abort_wq);
		if (ret)
			pr_err("failed qseecom_send_mod_resp: %d\n", ret);
		__qseecom_clean_data_sglistinfo(data);
		break;
	}
	case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: {
@@ -7174,12 +7296,6 @@ static int qseecom_open(struct inode *inode, struct file *file)
	data->mode = INACTIVE;
	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)) {
		kzfree(data);
		return -ENOMEM;
	}
	return ret;
}

@@ -7234,7 +7350,6 @@ 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;
@@ -7983,73 +8098,14 @@ out:
}

/*
 * Check if whitelist feature is supported by making a test scm_call
 * to send a whitelist command to an invalid app ID 0
 * Check whitelist feature, and if TZ feature version is < 1.0.0,
 * then whitelist feature is not supported.
 */
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;
	int version = scm_get_feat_version(FEATURE_ID_WHITELIST);

	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_info("Check whitelist with ret = %d, result = 0x%x\n",
			ret, resp.result);
		qseecom.whitelist_support = false;
		ret = 0;
	}
	kfree(buf);
	return ret;
	return version >= MAKE_WHITELIST_VERSION(1, 0, 0);
}

static int qseecom_probe(struct platform_device *pdev)
@@ -8300,11 +8356,7 @@ 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;
	}
	qseecom.whitelist_support = qseecom_check_whitelist_feature();
	pr_warn("qseecom.whitelist_support = %d\n",
				qseecom.whitelist_support);

+19 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ enum qseecom_qceos_cmd_id {
	QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C,
	QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D,
	QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E,
	QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F,
	QSEOS_FSM_LTEOTA_REQ_CMD = 0x109,
	QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110,
	QSEOS_FSM_IKE_REQ_CMD = 0x203,
@@ -217,6 +218,16 @@ __packed struct qseecom_client_listener_data_irsp {
	uint32_t qsee_cmd_id;
	uint32_t listener_id;
	uint32_t status;
	uint32_t sglistinfo_ptr;
	uint32_t sglistinfo_len;
};

__packed struct qseecom_client_listener_data_64bit_irsp {
	uint32_t qsee_cmd_id;
	uint32_t listener_id;
	uint32_t status;
	uint64_t sglistinfo_ptr;
	uint32_t sglistinfo_len;
};

/*
@@ -703,4 +714,12 @@ __packed struct qseecom_continue_blocked_request_ireq {
	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW,	\
	TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05)

#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_4( \
	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \
	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)

#endif /* __QSEECOMI_H_ */