qseecom: Check if app exists before loading the app

There is a chance of send a request to QSEE to load an app that
is already previously loaded. Requesting QSEE to load an app
that is already loaded will result in a failure.

Issuing a request to QSEE to check if app already exists before
issuing a request to load it, all within the same app_access_lock
mutex, fixes this issue.

CRs-Fixed: 420473
Change-Id: I5dfb02c7b0f0144d142fc70084ec1e096ada0439
Signed-off-by: Mona Hossain <mhossain@codeaurora.org>
This commit is contained in:
Mona Hossain 2012-11-20 17:10:40 -08:00 committed by Iliyan Malchev
parent 06bf8e423f
commit a572f57b1a

View file

@ -653,6 +653,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
ion_phys_addr_t pa = 0;
uint32_t len;
struct qseecom_command_scm_resp resp;
struct qseecom_check_app_ireq req;
struct qseecom_load_app_ireq load_req;
/* Copy the relevant information needed for loading the image */
@ -666,88 +667,112 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
ret = qsee_vote_for_clock(CLK_SFPB);
if (ret)
pr_warning("Unable to vote for SFPB clock");
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
pr_warn("App (%s) does not exist, loading apps for first time\n",
ret = __qseecom_check_app_exists(req);
if (ret < 0)
return ret;
else
app_id = ret;
if (app_id) {
pr_warn("App id %d (%s) already exists\n", app_id,
(char *)(req.app_name));
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
&qseecom.registered_app_list_head, list){
if (entry->app_id == app_id) {
entry->ref_cnt++;
break;
}
}
spin_unlock_irqrestore(
&qseecom.registered_app_list_lock, flags);
} else {
pr_warn("App (%s) does'nt exist, loading apps for first time\n",
(char *)(load_img_req.img_name));
/* Get the handle of the shared fd */
ihandle = ion_import_dma_buf(qseecom.ion_clnt,
/* Get the handle of the shared fd */
ihandle = ion_import_dma_buf(qseecom.ion_clnt,
load_img_req.ifd_data_fd);
if (IS_ERR_OR_NULL(ihandle)) {
pr_err("Ion client could not retrieve the handle\n");
qsee_disable_clock_vote(CLK_SFPB);
return -ENOMEM;
}
if (IS_ERR_OR_NULL(ihandle)) {
pr_err("Ion client could not retrieve the handle\n");
qsee_disable_clock_vote(CLK_SFPB);
return -ENOMEM;
}
/* Get the physical address of the ION BUF */
ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
/* Get the physical address of the ION BUF */
ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
/* Populate the structure for sending scm call to load image */
memcpy(load_req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
load_req.mdt_len = load_img_req.mdt_len;
load_req.img_len = load_img_req.img_len;
load_req.phy_addr = pa;
/* Populate the structure for sending scm call to load image */
memcpy(load_req.app_name, load_img_req.img_name,
MAX_APP_NAME_SIZE);
load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
load_req.mdt_len = load_img_req.mdt_len;
load_req.img_len = load_img_req.img_len;
load_req.phy_addr = pa;
/* SCM_CALL to load the app and get the app_id back */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
/* SCM_CALL to load the app and get the app_id back */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
sizeof(struct qseecom_load_app_ireq),
&resp, sizeof(resp));
if (ret) {
pr_err("scm_call to load app failed\n");
return -EINVAL;
}
if (resp.result == QSEOS_RESULT_FAILURE) {
pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
qsee_disable_clock_vote(CLK_SFPB);
return -EFAULT;
}
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
ret = __qseecom_process_incomplete_cmd(data, &resp);
if (ret) {
pr_err("process_incomplete_cmd failed err: %d\n",
ret);
pr_err("scm_call to load app failed\n");
return -EINVAL;
}
if (resp.result == QSEOS_RESULT_FAILURE) {
pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
qsee_disable_clock_vote(CLK_SFPB);
return ret;
return -EFAULT;
}
}
if (resp.result != QSEOS_RESULT_SUCCESS) {
pr_err("scm_call failed resp.result unknown, %d\n",
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
ret = __qseecom_process_incomplete_cmd(data, &resp);
if (ret) {
pr_err("process_incomplete_cmd failed err: %d\n",
ret);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
qsee_disable_clock_vote(CLK_SFPB);
return ret;
}
}
if (resp.result != QSEOS_RESULT_SUCCESS) {
pr_err("scm_call failed resp.result unknown, %d\n",
resp.result);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
qsee_disable_clock_vote(CLK_SFPB);
return -EFAULT;
}
app_id = resp.data;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
pr_err("kmalloc failed\n");
qsee_disable_clock_vote(CLK_SFPB);
return -ENOMEM;
}
entry->app_id = app_id;
entry->ref_cnt = 1;
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
qsee_disable_clock_vote(CLK_SFPB);
return -EFAULT;
}
app_id = resp.data;
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_add_tail(&entry->list, &qseecom.registered_app_list_head);
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
flags);
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
pr_err("kmalloc failed\n");
qsee_disable_clock_vote(CLK_SFPB);
return -ENOMEM;
}
entry->app_id = app_id;
entry->ref_cnt = 1;
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_add_tail(&entry->list, &qseecom.registered_app_list_head);
spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
pr_warn("App with id %d (%s) now loaded\n", app_id,
pr_warn("App with id %d (%s) now loaded\n", app_id,
(char *)(load_img_req.img_name));
}
data->client.app_id = app_id;
load_img_req.app_id = app_id;
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {