Loading drivers/misc/qseecom.c +103 −30 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ struct qseecom_registered_app_list { struct list_head list; u32 app_id; u32 ref_cnt; char app_name[MAX_APP_NAME_SIZE]; }; struct qseecom_registered_kclient_list { Loading Loading @@ -191,6 +192,7 @@ struct qseecom_client_handle { unsigned long user_virt_sb_base; size_t sb_length; struct ion_handle *ihandle; /* Retrieve phy addr */ char app_name[MAX_APP_NAME_SIZE]; }; struct qseecom_listener_handle { Loading Loading @@ -654,7 +656,6 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, return -EFAULT; data->listener.id = 0; data->type = QSEECOM_LISTENER_SERVICE; if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) { pr_err("Service is not unique and is already registered\n"); data->released = true; Loading Loading @@ -1308,7 +1309,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) } entry->app_id = app_id; entry->ref_cnt = 1; memset((void *)entry->app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)entry->app_name, (void *)load_img_req.img_name, MAX_APP_NAME_SIZE); /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); Loading @@ -1322,6 +1325,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) (char *)(load_img_req.img_name)); } data->client.app_id = app_id; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)data->client.app_name, (void *)load_img_req.img_name, MAX_APP_NAME_SIZE); load_img_req.app_id = app_id; if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { pr_err("copy_to_user failed\n"); Loading Loading @@ -1366,44 +1372,59 @@ static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data) return ret; } static int qseecom_unload_app(struct qseecom_dev_handle *data) static int qseecom_unload_app(struct qseecom_dev_handle *data, bool app_crash) { unsigned long flags; unsigned long flags1; int ret = 0; struct qseecom_command_scm_resp resp; struct qseecom_registered_app_list *ptr_app; struct qseecom_registered_app_list *ptr_app = NULL; bool unload = false; bool found_app = false; bool found_dead_app = false; if (!memcmp(data->client.app_name, "keymaste", strlen("keymaste"))) { pr_warn("Do not unload keymaster app from tz\n"); return 0; } if (data->client.app_id > 0) { spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, list) { if (ptr_app->app_id == data->client.app_id) { if (!memcmp((void *)ptr_app->app_name, (void *)data->client.app_name, strlen(data->client.app_name))) { found_app = true; if (ptr_app->ref_cnt == 1) { if (app_crash || ptr_app->ref_cnt == 1) unload = true; break; } else { ptr_app->ref_cnt--; pr_debug("Can't unload app(%d) inuse\n", ptr_app->app_id); found_dead_app = true; break; } } } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (found_app == false) { pr_err("Cannot find app with id = %d\n", data->client.app_id); if (found_app == false && found_dead_app == false) { pr_err("Cannot find app with id = %d (%s)\n", data->client.app_id, (char *)data->client.app_name); return -EINVAL; } } if (found_dead_app) { pr_warn("cleanup app_id %d(%s)\n", data->client.app_id, (char *)data->client.app_name); __qseecom_cleanup_app(data); } if (unload) { struct qseecom_unload_app_ireq req; /* Populate the structure for sending scm call to load image */ req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND; req.app_id = data->client.app_id; Loading @@ -1419,14 +1440,15 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data) } else { pr_warn("App id %d now unloaded\n", req.app_id); } if (resp.result == QSEOS_RESULT_FAILURE) { pr_err("app (%d) unload_failed!!\n", data->client.app_id); return -EFAULT; } if (resp.result == QSEOS_RESULT_SUCCESS) pr_debug("App (%d) is unloaded!!\n", data->client.app_id); __qseecom_cleanup_app(data); spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_del(&ptr_app->list); kzfree(ptr_app); spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (resp.result == QSEOS_RESULT_INCOMPLETE) { ret = __qseecom_process_incomplete_cmd(data, &resp); if (ret) { Loading @@ -1436,6 +1458,29 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data) } } } if (found_app) { spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1); if (app_crash) { ptr_app->ref_cnt = 0; pr_debug("app_crash: ref_count = 0\n"); } else { if (ptr_app->ref_cnt == 1) { ptr_app->ref_cnt = 0; pr_debug("ref_count set to 0\n"); } else { ptr_app->ref_cnt--; pr_debug("Can't unload app(%d) inuse\n", ptr_app->app_id); } } if (unload) { list_del(&ptr_app->list); kzfree(ptr_app); } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags1); } qseecom_unmap_ion_allocated_memory(data); data->released = true; return ret; Loading Loading @@ -1724,6 +1769,10 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; if (req->cmd_req_buf == NULL || req->resp_buf == NULL) { pr_err("cmd buffer or response buffer is null\n"); Loading Loading @@ -1771,6 +1820,27 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, return -EINVAL; } /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, list) { name_len = min(strlen(data->client.app_name), strlen(ptr_app->app_name)); if ((ptr_app->app_id == data->client.app_id) && (!memcmp((void *)ptr_app->app_name, (void *)data->client.app_name, name_len))) { found_app = true; break; } } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (!found_app) { pr_err("app_id %d (%s) is not found\n", data->client.app_id, (char *)data->client.app_name); return -EINVAL; } 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, Loading Loading @@ -2637,7 +2707,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) if (!found_handle) pr_err("Unable to find the handle, exiting\n"); else ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, false); if (qseecom.support_bus_scaling) { mutex_lock(&qsee_bw_mutex); Loading Loading @@ -3302,7 +3372,9 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, &qseecom.registered_app_list_lock, flags); data->client.app_id = ret; query_req.app_id = ret; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)data->client.app_name, (void *)query_req.app_name, MAX_APP_NAME_SIZE); if (copy_to_user(argp, &query_req, sizeof(query_req))) { pr_err("copy_to_user failed\n"); return -EFAULT; Loading Loading @@ -4279,7 +4351,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) pr_debug("UNLOAD_APP: qseecom_addr = 0x%p\n", data); mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, false); atomic_dec(&data->ioctl_count); mutex_unlock(&app_access_lock); if (ret) Loading Loading @@ -4638,6 +4710,7 @@ static int qseecom_open(struct inode *inode, struct file *file) data->abort = 0; data->type = QSEECOM_GENERIC; data->released = false; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); data->mode = INACTIVE; init_waitqueue_head(&data->abort_wq); atomic_set(&data->ioctl_count, 0); Loading @@ -4658,13 +4731,13 @@ static int qseecom_release(struct inode *inode, struct file *file) ret = qseecom_unregister_listener(data); break; case QSEECOM_CLIENT_APP: ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, true); break; case QSEECOM_SECURE_SERVICE: case QSEECOM_GENERIC: ret = qseecom_unmap_ion_allocated_memory(data); if (ret) pr_err("Close failed\n"); pr_err("Ion Unmap failed\n"); break; case QSEECOM_UNAVAILABLE_CLIENT_APP: break; Loading Loading @@ -5139,7 +5212,7 @@ static int qseecom_remove(struct platform_device *pdev) goto exit_free_kc_handle; list_del(&kclient->list); ret = qseecom_unload_app(kclient->handle->dev); ret = qseecom_unload_app(kclient->handle->dev, false); if (!ret) { kzfree(kclient->handle->dev); kzfree(kclient->handle); Loading Loading
drivers/misc/qseecom.c +103 −30 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ struct qseecom_registered_app_list { struct list_head list; u32 app_id; u32 ref_cnt; char app_name[MAX_APP_NAME_SIZE]; }; struct qseecom_registered_kclient_list { Loading Loading @@ -191,6 +192,7 @@ struct qseecom_client_handle { unsigned long user_virt_sb_base; size_t sb_length; struct ion_handle *ihandle; /* Retrieve phy addr */ char app_name[MAX_APP_NAME_SIZE]; }; struct qseecom_listener_handle { Loading Loading @@ -654,7 +656,6 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, return -EFAULT; data->listener.id = 0; data->type = QSEECOM_LISTENER_SERVICE; if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) { pr_err("Service is not unique and is already registered\n"); data->released = true; Loading Loading @@ -1308,7 +1309,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) } entry->app_id = app_id; entry->ref_cnt = 1; memset((void *)entry->app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)entry->app_name, (void *)load_img_req.img_name, MAX_APP_NAME_SIZE); /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); Loading @@ -1322,6 +1325,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) (char *)(load_img_req.img_name)); } data->client.app_id = app_id; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)data->client.app_name, (void *)load_img_req.img_name, MAX_APP_NAME_SIZE); load_img_req.app_id = app_id; if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { pr_err("copy_to_user failed\n"); Loading Loading @@ -1366,44 +1372,59 @@ static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data) return ret; } static int qseecom_unload_app(struct qseecom_dev_handle *data) static int qseecom_unload_app(struct qseecom_dev_handle *data, bool app_crash) { unsigned long flags; unsigned long flags1; int ret = 0; struct qseecom_command_scm_resp resp; struct qseecom_registered_app_list *ptr_app; struct qseecom_registered_app_list *ptr_app = NULL; bool unload = false; bool found_app = false; bool found_dead_app = false; if (!memcmp(data->client.app_name, "keymaste", strlen("keymaste"))) { pr_warn("Do not unload keymaster app from tz\n"); return 0; } if (data->client.app_id > 0) { spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, list) { if (ptr_app->app_id == data->client.app_id) { if (!memcmp((void *)ptr_app->app_name, (void *)data->client.app_name, strlen(data->client.app_name))) { found_app = true; if (ptr_app->ref_cnt == 1) { if (app_crash || ptr_app->ref_cnt == 1) unload = true; break; } else { ptr_app->ref_cnt--; pr_debug("Can't unload app(%d) inuse\n", ptr_app->app_id); found_dead_app = true; break; } } } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (found_app == false) { pr_err("Cannot find app with id = %d\n", data->client.app_id); if (found_app == false && found_dead_app == false) { pr_err("Cannot find app with id = %d (%s)\n", data->client.app_id, (char *)data->client.app_name); return -EINVAL; } } if (found_dead_app) { pr_warn("cleanup app_id %d(%s)\n", data->client.app_id, (char *)data->client.app_name); __qseecom_cleanup_app(data); } if (unload) { struct qseecom_unload_app_ireq req; /* Populate the structure for sending scm call to load image */ req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND; req.app_id = data->client.app_id; Loading @@ -1419,14 +1440,15 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data) } else { pr_warn("App id %d now unloaded\n", req.app_id); } if (resp.result == QSEOS_RESULT_FAILURE) { pr_err("app (%d) unload_failed!!\n", data->client.app_id); return -EFAULT; } if (resp.result == QSEOS_RESULT_SUCCESS) pr_debug("App (%d) is unloaded!!\n", data->client.app_id); __qseecom_cleanup_app(data); spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_del(&ptr_app->list); kzfree(ptr_app); spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (resp.result == QSEOS_RESULT_INCOMPLETE) { ret = __qseecom_process_incomplete_cmd(data, &resp); if (ret) { Loading @@ -1436,6 +1458,29 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data) } } } if (found_app) { spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1); if (app_crash) { ptr_app->ref_cnt = 0; pr_debug("app_crash: ref_count = 0\n"); } else { if (ptr_app->ref_cnt == 1) { ptr_app->ref_cnt = 0; pr_debug("ref_count set to 0\n"); } else { ptr_app->ref_cnt--; pr_debug("Can't unload app(%d) inuse\n", ptr_app->app_id); } } if (unload) { list_del(&ptr_app->list); kzfree(ptr_app); } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags1); } qseecom_unmap_ion_allocated_memory(data); data->released = true; return ret; Loading Loading @@ -1724,6 +1769,10 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; if (req->cmd_req_buf == NULL || req->resp_buf == NULL) { pr_err("cmd buffer or response buffer is null\n"); Loading Loading @@ -1771,6 +1820,27 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, return -EINVAL; } /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, list) { name_len = min(strlen(data->client.app_name), strlen(ptr_app->app_name)); if ((ptr_app->app_id == data->client.app_id) && (!memcmp((void *)ptr_app->app_name, (void *)data->client.app_name, name_len))) { found_app = true; break; } } spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (!found_app) { pr_err("app_id %d (%s) is not found\n", data->client.app_id, (char *)data->client.app_name); return -EINVAL; } 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, Loading Loading @@ -2637,7 +2707,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) if (!found_handle) pr_err("Unable to find the handle, exiting\n"); else ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, false); if (qseecom.support_bus_scaling) { mutex_lock(&qsee_bw_mutex); Loading Loading @@ -3302,7 +3372,9 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, &qseecom.registered_app_list_lock, flags); data->client.app_id = ret; query_req.app_id = ret; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); memcpy((void *)data->client.app_name, (void *)query_req.app_name, MAX_APP_NAME_SIZE); if (copy_to_user(argp, &query_req, sizeof(query_req))) { pr_err("copy_to_user failed\n"); return -EFAULT; Loading Loading @@ -4279,7 +4351,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) pr_debug("UNLOAD_APP: qseecom_addr = 0x%p\n", data); mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, false); atomic_dec(&data->ioctl_count); mutex_unlock(&app_access_lock); if (ret) Loading Loading @@ -4638,6 +4710,7 @@ static int qseecom_open(struct inode *inode, struct file *file) data->abort = 0; data->type = QSEECOM_GENERIC; data->released = false; memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE); data->mode = INACTIVE; init_waitqueue_head(&data->abort_wq); atomic_set(&data->ioctl_count, 0); Loading @@ -4658,13 +4731,13 @@ static int qseecom_release(struct inode *inode, struct file *file) ret = qseecom_unregister_listener(data); break; case QSEECOM_CLIENT_APP: ret = qseecom_unload_app(data); ret = qseecom_unload_app(data, true); break; case QSEECOM_SECURE_SERVICE: case QSEECOM_GENERIC: ret = qseecom_unmap_ion_allocated_memory(data); if (ret) pr_err("Close failed\n"); pr_err("Ion Unmap failed\n"); break; case QSEECOM_UNAVAILABLE_CLIENT_APP: break; Loading Loading @@ -5139,7 +5212,7 @@ static int qseecom_remove(struct platform_device *pdev) goto exit_free_kc_handle; list_del(&kclient->list); ret = qseecom_unload_app(kclient->handle->dev); ret = qseecom_unload_app(kclient->handle->dev, false); if (!ret) { kzfree(kclient->handle->dev); kzfree(kclient->handle); Loading