Merge "qseecom: support whitelist memory for qseecom_send_modfd_cmd"

This commit is contained in:
Linux Build Service Account 2016-08-26 14:48:39 -07:00 committed by Gerrit - the friendly Code Review server
commit 158d2d87fe
2 changed files with 377 additions and 46 deletions

View file

@ -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;
@ -2632,14 +2751,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 */
@ -2661,7 +2781,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));
@ -2669,11 +2788,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);
@ -2695,10 +2817,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,
@ -2952,14 +3084,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);
@ -3158,14 +3302,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);
@ -5828,14 +5983,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);
@ -5860,6 +6024,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)
@ -5882,8 +6047,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);
@ -5891,10 +6063,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);
@ -5914,17 +6089,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,
@ -6022,6 +6199,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));
@ -6033,6 +6213,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);
@ -6051,31 +6233,6 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
return -ENOENT;
}
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);
ireq.req_len = req.req_len;
ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
(uintptr_t)req.resp_ptr);
ireq.resp_len = req.resp_len;
cmd_buf = (void *)&ireq;
cmd_len = sizeof(struct qseecom_qteec_ireq);
} 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);
ireq_64bit.req_len = req.req_len;
ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
(uintptr_t)req.resp_ptr);
ireq_64bit.resp_len = req.resp_len;
cmd_buf = (void *)&ireq_64bit;
cmd_len = sizeof(struct qseecom_qteec_64bit_ireq);
}
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) {
@ -6090,6 +6247,42 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
ret = __qseecom_update_qteec_req_buf(&req, data, false);
if (ret)
return ret;
if (qseecom.qsee_version < QSEE_VERSION_40) {
ireq.app_id = data->client.app_id;
ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
(uintptr_t)req_ptr);
ireq.req_len = req.req_len;
ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
(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.app_id = data->client.app_id;
ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
(uintptr_t)req_ptr);
ireq_64bit.req_len = req.req_len;
ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
(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;
msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
data->client.sb_virt,
reqd_len_sb_in,
@ -6152,6 +6345,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;
@ -6331,6 +6533,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: {
@ -6728,6 +6931,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: {
@ -6776,6 +6980,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: {
@ -6852,6 +7057,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;
}
@ -6906,6 +7114,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;
@ -7653,6 +7862,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;
@ -7685,6 +7962,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) {
@ -7900,6 +8178,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");

View file

@ -1,5 +1,5 @@
/*
* 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_ */