mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
631 lines
22 KiB
Diff
631 lines
22 KiB
Diff
|
From 9bd398661cae758ffc557adc7de74ba32654e1f9 Mon Sep 17 00:00:00 2001
|
||
|
From: Zhen Kong <zkong@codeaurora.org>
|
||
|
Date: Fri, 2 Sep 2016 22:09:23 -0700
|
||
|
Subject: qseecom: whitelist support for kernel client and listener
|
||
|
|
||
|
-- Add whitelist support for listener to send modified resp to TZ;
|
||
|
-- support whitelist for kernel client;
|
||
|
-- Change the method to check whitelist feature.
|
||
|
|
||
|
Change-Id: I0030b0008d6224cda3fdc1f80308a7e9bcfe4405
|
||
|
Signed-off-by: Zhen Kong <zkong@codeaurora.org>
|
||
|
---
|
||
|
drivers/misc/qseecom.c | 322 +++++++++++++++++++++++++-------------------
|
||
|
include/soc/qcom/qseecomi.h | 19 +++
|
||
|
2 files changed, 206 insertions(+), 135 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
|
||
|
index 061bc99..35f0b94 100644
|
||
|
--- a/drivers/misc/qseecom.c
|
||
|
+++ b/drivers/misc/qseecom.c
|
||
|
@@ -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;
|
||
|
@@ -1124,7 +1160,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;
|
||
|
@@ -1585,6 +1621,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)
|
||
|
{
|
||
|
@@ -1593,9 +1639,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;
|
||
|
@@ -1669,15 +1720,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;
|
||
|
- send_data_rsp.listener_id = lstnr;
|
||
|
+ 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,
|
||
|
@@ -1687,10 +1765,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);
|
||
|
@@ -1818,9 +1895,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;
|
||
|
@@ -1883,13 +1965,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;
|
||
|
- send_data_rsp.listener_id = lstnr;
|
||
|
+ 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,
|
||
|
@@ -1899,11 +2006,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) {
|
||
|
@@ -2901,7 +3006,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;
|
||
|
@@ -3006,6 +3111,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))
|
||
|
@@ -3027,7 +3134,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,
|
||
|
@@ -3169,14 +3275,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 */
|
||
|
@@ -3249,6 +3366,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))
|
||
|
@@ -3270,7 +3389,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,
|
||
|
@@ -3387,14 +3505,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 */
|
||
|
@@ -4091,21 +4220,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;
|
||
|
@@ -4203,7 +4323,6 @@ int qseecom_start_app(struct qseecom_handle **handle,
|
||
|
return 0;
|
||
|
|
||
|
err:
|
||
|
- kfree(data->sglistinfo_ptr);
|
||
|
kfree(data);
|
||
|
kfree(*handle);
|
||
|
*handle = NULL;
|
||
|
@@ -4251,7 +4370,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);
|
||
|
@@ -4317,8 +4435,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);
|
||
|
@@ -6990,6 +7111,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: {
|
||
|
@@ -7139,12 +7261,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;
|
||
|
}
|
||
|
|
||
|
@@ -7199,7 +7315,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;
|
||
|
@@ -7948,73 +8063,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)
|
||
|
@@ -8265,11 +8321,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);
|
||
|
|
||
|
diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h
|
||
|
index b0a8d67..e33fd9f 100644
|
||
|
--- a/include/soc/qcom/qseecomi.h
|
||
|
+++ b/include/soc/qcom/qseecomi.h
|
||
|
@@ -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_ */
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|