summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrthavti <quic_rthavti@quicinc.com>2023-01-27 18:32:10 +0530
committerrthavti <quic_rthavti@quicinc.com>2023-01-27 18:32:10 +0530
commit8e601de94bc895ab77c27890347ca04d15a24b4a (patch)
tree4e2942dc614c5d7ca4f44e5f43476b38aea73e39
parent55d4cd3ca27291ade75309ac3cfe28cd7000dc8e (diff)
parent0e92ea4387f8c0a4d295b10dfa07f7155455ab84 (diff)
downloadsecuremsm-8e601de94bc895ab77c27890347ca04d15a24b4a.tar.gz
Merge commit '0e92ea4387f8c0a4d295b10dfa07f7155455ab84' into sec-kernel.lnx.13.1.r9-rel
Change-Id: I8ff4752aab38ed594dabb1539bbe250653d0ce7a
-rw-r--r--Kbuild7
-rw-r--r--crypto-qti/qce.h11
-rw-r--r--crypto-qti/qce50.c100
-rw-r--r--crypto-qti/qce50.h1
-rw-r--r--crypto-qti/qcedev.c88
-rw-r--r--qseecom/qseecom.c261
-rw-r--r--qseecom/qseecom_32bit_impl.c943
-rw-r--r--qseecom/qseecom_32bit_impl.h341
-rw-r--r--securemsm_kernel_vendor_board.mk4
-rw-r--r--smcinvoke/IClientEnv.h13
-rw-r--r--smcinvoke/smcinvoke.c90
-rw-r--r--smcinvoke/smcinvoke_kernel.c11
-rw-r--r--smcinvoke/smcinvoke_object.h1
13 files changed, 1724 insertions, 147 deletions
diff --git a/Kbuild b/Kbuild
index fce1e73..baa2908 100644
--- a/Kbuild
+++ b/Kbuild
@@ -7,12 +7,15 @@ ifneq ($(CONFIG_ARCH_QTI_VM), y)
endif
#Enable Qseecom if CONFIG_ARCH_KHAJE OR CONFIG_ARCH_KHAJE or CONFIG_QTI_QUIN_GVM or CONFIG_ARCH_MONACO or CONFIG_ARCH_SCUBA_AUTO or CONFIG_ARCH_SA410M is set to y
-ifneq (, $(filter y, $(CONFIG_QTI_QUIN_GVM) $(CONFIG_ARCH_KHAJE) $(CONFIG_ARCH_SA8155) $(CONFIG_ARCH_MONACO) $(CONFIG_ARCH_SCUBA_AUTO) $(CONFIG_ARCH_SA410M)))
+ifneq (, $(filter y, $(CONFIG_QTI_QUIN_GVM) $(CONFIG_ARCH_KHAJE) $(CONFIG_ARCH_SA8155) $(CONFIG_ARCH_LEMANS) $(CONFIG_ARCH_MONACO) $(CONFIG_ARCH_SCUBA_AUTO) $(CONFIG_ARCH_SA410M)))
include $(SSG_MODULE_ROOT)/config/sec-kernel_defconfig_qseecom.conf
LINUXINCLUDE += -include $(SSG_MODULE_ROOT)/config/sec-kernel_defconfig_qseecom.h
obj-$(CONFIG_QSEECOM) += qseecom_dlkm.o
- qseecom_dlkm-objs := qseecom/qseecom.o qseecom/compat_qseecom.o
+ qseecom_dlkm-objs := qseecom/qseecom.o
+ ifdef CONFIG_COMPAT
+ qseecom_dlkm-objs += qseecom/qseecom_32bit_impl.o
+ endif
endif
include $(SSG_MODULE_ROOT)/config/sec-kernel_defconfig_smcinvoke.conf
diff --git a/crypto-qti/qce.h b/crypto-qti/qce.h
index f461924..6d6f6ff 100644
--- a/crypto-qti/qce.h
+++ b/crypto-qti/qce.h
@@ -198,6 +198,13 @@ struct qce_pm_table {
extern struct qce_pm_table qce_pm_table;
+struct qce_error {
+ bool no_error;
+ bool timer_error;
+ bool key_paused;
+ bool generic_error;
+};
+
void *qce_open(struct platform_device *pdev, int *rc);
int qce_close(void *handle);
int qce_aead_req(void *handle, struct qce_req *req);
@@ -209,9 +216,7 @@ int qce_disable_clk(void *handle);
void qce_get_driver_stats(void *handle);
void qce_clear_driver_stats(void *handle);
void qce_dump_req(void *handle);
-void qce_get_crypto_status(void *handle, unsigned int *s1, unsigned int *s2,
- unsigned int *s3, unsigned int *s4,
- unsigned int *s5, unsigned int *s6);
+void qce_get_crypto_status(void *handle, struct qce_error *error);
int qce_manage_timeout(void *handle, int req_info);
int qce_set_irqs(void *handle, bool enable);
#endif /* __CRYPTO_MSM_QCE_H */
diff --git a/crypto-qti/qce50.c b/crypto-qti/qce50.c
index d6a762f..0521ed6 100644
--- a/crypto-qti/qce50.c
+++ b/crypto-qti/qce50.c
@@ -85,7 +85,26 @@ static LIST_HEAD(qce50_bam_list);
#define TOTAL_IOVEC_SPACE_PER_PIPE (QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec))
#define AES_CTR_IV_CTR_SIZE 64
-#define STATUS1_ERR_INTR_MASK 0x10
+
+#define QCE_STATUS1_NO_ERROR 0x2000006
+
+// Crypto Engines 5.7 and below
+// Key timer expiry for pipes 1-15 (Status3)
+#define CRYPTO5_LEGACY_TIMER_EXPIRED_STATUS3 0x0000FF00
+// Key timer expiry for pipes 16-19 (Status6)
+#define CRYPTO5_LEGACY_TIMER_EXPIRED_STATUS6 0x00000300
+// Key pause for pipes 1-15 (Status3)
+#define CRYPTO5_LEGACY_KEY_PAUSE_STATUS3 0xFF000000
+// Key pause for pipes 16-19 (Status6)
+#define CRYPTO5_LEGACY_KEY_PAUSE_STATUS6 0x3000000
+
+// Crypto Engines 5.8 and above
+// Key timer expiry for all pipes (Status3)
+#define CRYPTO58_TIMER_EXPIRED 0x00000010
+// Key pause for all pipes (Status3)
+#define CRYPTO58_KEY_PAUSE 0x00001000
+// Key index for Status3 (Timer and Key Pause)
+#define KEY_INDEX_SHIFT 16
enum qce_owner {
QCE_OWNER_NONE = 0,
@@ -201,36 +220,72 @@ static uint32_t qce_get_config_be(struct qce_device *pce_dev,
pipe_pair << CRYPTO_PIPE_SET_SELECT);
}
-static void dump_status_regs(unsigned int s1, unsigned int s2,unsigned int s3,
- unsigned int s4, unsigned int s5,unsigned int s6)
+static void dump_status_regs(unsigned int *status)
{
- pr_info("%s: CRYPTO_STATUS_REG = 0x%x\n", __func__, s1);
- pr_info("%s: CRYPTO_STATUS2_REG = 0x%x\n", __func__, s2);
- pr_info("%s: CRYPTO_STATUS3_REG = 0x%x\n", __func__, s3);
- pr_info("%s: CRYPTO_STATUS4_REG = 0x%x\n", __func__, s4);
- pr_info("%s: CRYPTO_STATUS5_REG = 0x%x\n", __func__, s5);
- pr_info("%s: CRYPTO_STATUS6_REG = 0x%x\n", __func__, s6);
+ pr_info("%s: CRYPTO_STATUS_REG = 0x%x\n", __func__, status[0]);
+ pr_info("%s: CRYPTO_STATUS2_REG = 0x%x\n", __func__, status[1]);
+ pr_info("%s: CRYPTO_STATUS3_REG = 0x%x\n", __func__, status[2]);
+ pr_info("%s: CRYPTO_STATUS4_REG = 0x%x\n", __func__, status[3]);
+ pr_info("%s: CRYPTO_STATUS5_REG = 0x%x\n", __func__, status[4]);
+ pr_info("%s: CRYPTO_STATUS6_REG = 0x%x\n", __func__, status[5]);
}
-void qce_get_crypto_status(void *handle, unsigned int *s1, unsigned int *s2,
- unsigned int *s3, unsigned int *s4,
- unsigned int *s5, unsigned int *s6)
+void qce_get_crypto_status(void *handle, struct qce_error *error)
{
struct qce_device *pce_dev = (struct qce_device *) handle;
+ unsigned int status[6] = {0};
- *s1 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
- *s2 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS2_REG);
- *s3 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS3_REG);
- *s4 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS4_REG);
- *s5 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS5_REG);
- *s6 = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS6_REG);
+ status[0] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+ status[1] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS2_REG);
+ status[2] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS3_REG);
+ status[3] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS4_REG);
+ status[4] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS5_REG);
+ status[5] = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS6_REG);
#ifdef QCE_DEBUG
- dump_status_regs(*s1, *s2, *s3, *s4, *s5, *s6);
-#else
- if (*s1 & STATUS1_ERR_INTR_MASK)
- dump_status_regs(*s1, *s2, *s3, *s4, *s5, *s6);
+ dump_status_regs(&status[0]);
#endif
+
+ if (status[0] == QCE_STATUS1_NO_ERROR) {
+ error->no_error = true;
+ pr_err("%s: No crypto error, status1 = 0x%x\n",
+ __func__, status[0]);
+ } else {
+ if (pce_dev->ce_bam_info.minor_version >= 8) {
+ if (status[2] & CRYPTO58_TIMER_EXPIRED) {
+ error->timer_error = true;
+ pr_err("%s: timer expired, index = 0x%x\n",
+ __func__, (status[2] >> KEY_INDEX_SHIFT));
+ } else if (status[2] & CRYPTO58_KEY_PAUSE) {
+ error->key_paused = true;
+ pr_err("%s: key paused, index = 0x%x\n",
+ __func__, (status[2] >> KEY_INDEX_SHIFT));
+ } else {
+ pr_err("%s: generic error, refer all status\n",
+ __func__);
+ error->generic_error = true;
+ }
+ } else {
+ if ((status[2] & CRYPTO5_LEGACY_TIMER_EXPIRED_STATUS3) ||
+ (status[5] & CRYPTO5_LEGACY_TIMER_EXPIRED_STATUS6)) {
+ error->timer_error = true;
+ pr_err("%s: timer expired, refer status 3 and 6\n",
+ __func__);
+ }
+ else if ((status[2] & CRYPTO5_LEGACY_KEY_PAUSE_STATUS3) ||
+ (status[5] & CRYPTO5_LEGACY_KEY_PAUSE_STATUS6)) {
+ error->key_paused = true;
+ pr_err("%s: key paused, reder status 3 and 6\n",
+ __func__);
+ } else {
+ pr_err("%s: generic error, refer all status\n",
+ __func__);
+ error->generic_error = true;
+ }
+ }
+ dump_status_regs(&status[0]);
+ }
+
return;
}
EXPORT_SYMBOL(qce_get_crypto_status);
@@ -414,6 +469,7 @@ static int _probe_ce_engine(struct qce_device *pce_dev)
pce_dev->no_ccm_mac_status_get_around = false;
pce_dev->ce_bam_info.minor_version = min_rev;
+ pce_dev->ce_bam_info.major_version = maj_rev;
pce_dev->engines_avail = readl_relaxed(pce_dev->iobase +
CRYPTO_ENGINES_AVAIL);
diff --git a/crypto-qti/qce50.h b/crypto-qti/qce50.h
index e679df0..c8df639 100644
--- a/crypto-qti/qce50.h
+++ b/crypto-qti/qce50.h
@@ -200,6 +200,7 @@ struct ce_bam_info {
unsigned long bam_handle;
int ce_burst_size;
uint32_t minor_version;
+ uint32_t major_version;
struct qce_sps_ep_conn_data producer[QCE_OFFLOAD_OPER_LAST];
struct qce_sps_ep_conn_data consumer[QCE_OFFLOAD_OPER_LAST];
};
diff --git a/crypto-qti/qcedev.c b/crypto-qti/qcedev.c
index c7ef677..d1a238e 100644
--- a/crypto-qti/qcedev.c
+++ b/crypto-qti/qcedev.c
@@ -71,17 +71,6 @@ static uint8_t _std_init_vector_sha256_uint8[] = {
#define QCEDEV_CTX_USE_HW_KEY 0x00000001
#define QCEDEV_CTX_USE_PIPE_KEY 0x00000002
-// Key timer expiry for pipes 1-15 (Status3)
-#define PIPE_KEY_TIMER_EXPIRED_STATUS3_MASK 0x000000FF
-// Key timer expiry for pipes 16-19 (Status6)
-#define PIPE_KEY_TIMER_EXPIRED_STATUS6_MASK 0x00000003
-// Key pause for pipes 1-15 (Status3)
-#define PIPE_KEY_PAUSE_STATUS3_MASK 0xFF0000
-// Key pause for pipes 16-19 (Status6)
-#define PIPE_KEY_PAUSE_STATUS6_MASK 0x30000
-
-#define QCEDEV_STATUS1_ERR_INTR_MASK 0x10
-
static DEFINE_MUTEX(send_cmd_lock);
static DEFINE_MUTEX(qcedev_sent_bw_req);
static DEFINE_MUTEX(hash_access_lock);
@@ -707,53 +696,29 @@ static int start_sha_req(struct qcedev_control *podev,
};
static void qcedev_check_crypto_status(
- struct qcedev_async_req *qcedev_areq, void *handle,
- bool print_err)
+ struct qcedev_async_req *qcedev_areq, void *handle)
{
- unsigned int s1, s2, s3, s4, s5, s6;
+ struct qce_error error = {0};
qcedev_areq->offload_cipher_op_req.err = QCEDEV_OFFLOAD_NO_ERROR;
- qce_get_crypto_status(handle, &s1, &s2, &s3, &s4, &s5, &s6);
-
- if (print_err) {
- pr_err("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
- s1, s2, s3, s4, s5, s6);
- }
+ qce_get_crypto_status(handle, &error);
- // Check for key timer expiry
- if ((s6 & PIPE_KEY_TIMER_EXPIRED_STATUS6_MASK) ||
- (s3 & PIPE_KEY_TIMER_EXPIRED_STATUS3_MASK)) {
- pr_info("%s: crypto timer expired\n", __func__);
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
- s1, s2, s3, s4, s5, s6);
+ if (error.timer_error) {
qcedev_areq->offload_cipher_op_req.err =
- QCEDEV_OFFLOAD_KEY_TIMER_EXPIRED_ERROR;
- return;
- }
-
- // Check for key pause
- if ((s6 & PIPE_KEY_PAUSE_STATUS6_MASK) ||
- (s3 & PIPE_KEY_PAUSE_STATUS3_MASK)) {
- pr_info("%s: crypto key paused\n", __func__);
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
- s1, s2, s3, s4, s5, s6);
+ QCEDEV_OFFLOAD_KEY_TIMER_EXPIRED_ERROR;
+ } else if (error.key_paused) {
qcedev_areq->offload_cipher_op_req.err =
- QCEDEV_OFFLOAD_KEY_PAUSE_ERROR;
- return;
- }
-
- // Check for generic error
- if (s1 & QCEDEV_STATUS1_ERR_INTR_MASK) {
- pr_err("%s: generic crypto error\n", __func__);
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
- s1, s2, s3, s4, s5, s6);
+ QCEDEV_OFFLOAD_KEY_PAUSE_ERROR;
+ } else if (error.generic_error) {
qcedev_areq->offload_cipher_op_req.err =
- QCEDEV_OFFLOAD_GENERIC_ERROR;
- return;
+ QCEDEV_OFFLOAD_GENERIC_ERROR;
}
+
+ return;
}
-#define MAX_RETRIES 333
+
+#define MAX_RETRIES 333
static int submit_req(struct qcedev_async_req *qcedev_areq,
struct qcedev_handle *handle)
@@ -764,7 +729,6 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
struct qcedev_stat *pstat;
int current_req_info = 0;
int wait = MAX_CRYPTO_WAIT_TIME;
- bool print_sts = false;
struct qcedev_async_req *new_req = NULL;
int retries = 0;
int req_wait = MAX_REQUEST_TIME;
@@ -773,7 +737,6 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
podev = handle->cntl;
init_waitqueue_head(&qcedev_areq->wait_q);
-
spin_lock_irqsave(&podev->lock, flags);
/*
@@ -852,25 +815,26 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
*/
pr_err("%s: wait timed out, req info = %d\n", __func__,
current_req_info);
- print_sts = true;
- spin_lock_irqsave(&podev->lock, flags);
- qcedev_check_crypto_status(qcedev_areq, podev->qce, print_sts);
- qcedev_areq->timed_out = true;
- ret = qce_manage_timeout(podev->qce, current_req_info);
- spin_unlock_irqrestore(&podev->lock, flags);
- if (ret) {
- pr_err("%s: error during manage timeout", __func__);
+ qcedev_check_crypto_status(qcedev_areq, podev->qce);
+ if (qcedev_areq->offload_cipher_op_req.err ==
+ QCEDEV_OFFLOAD_NO_ERROR) {
+ pr_err("%s: no error, wait for request to be done", __func__);
while (qcedev_areq->state != QCEDEV_REQ_DONE &&
- retries < MAX_RETRIES) {
+ retries < MAX_RETRIES) {
usleep_range(3000, 5000);
retries++;
pr_err("%s: waiting for req state to be done, retries = %d",
- __func__, retries);
+ __func__, retries);
}
- // This means there is no crypto error, timeout corner case.
- qcedev_areq->offload_cipher_op_req.err = QCEDEV_OFFLOAD_NO_ERROR;
return 0;
}
+ spin_lock_irqsave(&podev->lock, flags);
+ qcedev_areq->timed_out = true;
+ ret = qce_manage_timeout(podev->qce, current_req_info);
+ if (ret)
+ pr_err("%s: error during manage timeout", __func__);
+
+ spin_unlock_irqrestore(&podev->lock, flags);
tasklet_schedule(&podev->done_tasklet);
if (qcedev_areq->offload_cipher_op_req.err !=
QCEDEV_OFFLOAD_NO_ERROR)
diff --git a/qseecom/qseecom.c b/qseecom/qseecom.c
index 8aac9c8..362f2b2 100644
--- a/qseecom/qseecom.c
+++ b/qseecom/qseecom.c
@@ -54,7 +54,7 @@
#include "misc/qseecom_kernel.h"
#endif
#if IS_ENABLED(CONFIG_COMPAT)
-#include "compat_qseecom.h"
+#include "qseecom_32bit_impl.h"
#endif
#define QSEECOM_DEV "qseecom"
@@ -118,6 +118,25 @@
#define FDE_FLAG_POS 4
#define ENABLE_KEY_WRAP_IN_KS (1 << FDE_FLAG_POS)
+#define K_COPY_FROM_USER(err, dst, src, size) \
+ do {\
+ if (!(CONFIG_COMPAT))\
+ err = copy_from_user((dst),\
+ (void const __user *)(src),\
+ (size));\
+ else\
+ memmove((dst), (src), (size));\
+ } while (0)
+
+#define K_COPY_TO_USER(err, dst, src, size) \
+ do {\
+ if(!(CONFIG_COMPAT))\
+ err = copy_to_user((void __user *)(dst),\
+ (src), (size));\
+ else\
+ memmove((dst), (src), (size));\
+ } while (0)
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -297,6 +316,7 @@ struct qseecom_control {
bool whitelist_support;
bool commonlib_loaded;
bool commonlib64_loaded;
+ bool commonlib_loaded_by_hostvm;
struct ce_hw_usage_info ce_info;
int qsee_bw_count;
@@ -1514,7 +1534,11 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
struct qseecom_registered_listener_list *new_entry;
struct qseecom_registered_listener_list *ptr_svc;
- memcpy(&rcvd_lstnr, argp, sizeof(rcvd_lstnr));
+ K_COPY_FROM_USER(ret, &rcvd_lstnr, argp, sizeof(rcvd_lstnr));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (!access_ok((void __user *)rcvd_lstnr.virt_sb_base,
rcvd_lstnr.sb_size))
return -EFAULT;
@@ -1925,7 +1949,11 @@ static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data,
if (qseecom.no_clock_support)
return 0;
- memcpy(&req_mode, argp, sizeof(req_mode));
+ K_COPY_FROM_USER(ret, &req_mode, argp, sizeof(req_mode));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (req_mode > HIGH) {
pr_err("Invalid bandwidth mode (%d)\n", req_mode);
return -EINVAL;
@@ -1998,12 +2026,14 @@ static int __qseecom_enable_clk_scale_up(struct qseecom_dev_handle *data)
static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
void __user *argp)
{
- int32_t ret;
+ int32_t ret = 0;
struct qseecom_set_sb_mem_param_req req;
size_t len;
/* Copy the relevant information needed for loading the image */
- memcpy(&req, (void __user *)argp, sizeof(req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(req));
+ if(ret)
+ return -EFAULT;
if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == NULL) ||
(req.sb_len == 0)) {
@@ -2751,11 +2781,16 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
bool first_time = false;
/* Copy the relevant information needed for loading the image */
- memcpy(&load_img_req, (void __user *)argp, sizeof(struct qseecom_load_img_req));
-
+ K_COPY_FROM_USER(ret, &load_img_req, argp,
+ sizeof(struct qseecom_load_img_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
/* Check and load cmnlib */
if (qseecom.qsee_version > QSEEE_VERSION_00) {
- if (!qseecom.commonlib_loaded &&
+ if (!(qseecom.commonlib_loaded ||
+ qseecom.commonlib_loaded_by_hostvm) &&
load_img_req.app_arch == ELFCLASS32) {
ret = qseecom_load_commonlib_image(data, "cmnlib");
if (ret) {
@@ -2766,7 +2801,8 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
pr_debug("cmnlib is loaded\n");
}
- if (!qseecom.commonlib64_loaded &&
+ if (!(qseecom.commonlib64_loaded ||
+ qseecom.commonlib_loaded_by_hostvm) &&
load_img_req.app_arch == ELFCLASS64) {
ret = qseecom_load_commonlib_image(data, "cmnlib64");
if (ret) {
@@ -2969,7 +3005,19 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
MAX_APP_NAME_SIZE);
load_img_req.app_id = app_id;
- memcpy(argp, &load_img_req, sizeof(load_img_req));
+ K_COPY_TO_USER(ret, argp, &load_img_req, sizeof(load_img_req));
+ if(ret) {
+ pr_err("copy_to_user failed\n");
+ ret = -EFAULT;
+ if (first_time) {
+ spin_lock_irqsave(
+ &qseecom.registered_app_list_lock, flags);
+ list_del(&entry->list);
+ spin_unlock_irqrestore(
+ &qseecom.registered_app_list_lock, flags);
+ kfree_sensitive(entry);
+ }
+ }
loadapp_err:
if (dmabuf) {
@@ -3424,8 +3472,12 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data,
size_t req_buf_size;
/*struct qseecom_command_scm_resp resp;*/
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
- memcpy(&req, (void __user *)argp, sizeof(req));
if (__validate_send_service_cmd_inputs(data, &req))
return -EINVAL;
@@ -3819,7 +3871,11 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp)
int ret = 0;
struct qseecom_send_cmd_req req;
- memcpy(&req, argp, sizeof(req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (__validate_send_cmd_inputs(data, &req))
return -EINVAL;
@@ -4312,7 +4368,11 @@ static int __qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
phys_addr_t pa;
u8 *va = NULL;
- memcpy(&req, argp, sizeof(req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
send_cmd_req.cmd_req_buf = req.cmd_req_buf;
send_cmd_req.cmd_req_len = req.cmd_req_len;
@@ -4703,7 +4763,9 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname,
/* Check and load cmnlib */
if (qseecom.qsee_version > QSEEE_VERSION_00) {
- if (!qseecom.commonlib_loaded && app_arch == ELFCLASS32) {
+ if (!(qseecom.commonlib_loaded ||
+ qseecom.commonlib_loaded_by_hostvm) &&
+ app_arch == ELFCLASS32) {
ret = qseecom_load_commonlib_image(data, "cmnlib");
if (ret) {
pr_err("failed to load cmnlib\n");
@@ -4713,7 +4775,9 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname,
pr_debug("cmnlib is loaded\n");
}
- if (!qseecom.commonlib64_loaded && app_arch == ELFCLASS64) {
+ if (!(qseecom.commonlib64_loaded ||
+ qseecom.commonlib_loaded_by_hostvm) &&
+ app_arch == ELFCLASS64) {
ret = qseecom_load_commonlib_image(data, "cmnlib64");
if (ret) {
pr_err("failed to load cmnlib64\n");
@@ -5246,8 +5310,10 @@ static int __qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
}
perf_enabled = true;
}
- if (!strcmp(data->client.app_name, "securemm"))
+ if (!strcmp(data->client.app_name, "securemm") ||
+ !strcmp(data->client.app_name, "slateapp")) {
data->use_legacy_cmd = true;
+ }
ret = __qseecom_send_cmd(data, &req, false);
@@ -5470,8 +5536,14 @@ static int __qseecom_send_modfd_resp(struct qseecom_dev_handle *data,
{
struct qseecom_send_modfd_listener_resp resp;
struct qseecom_registered_listener_list *this_lstnr = NULL;
+ int err = 0;
+
+ K_COPY_FROM_USER(err, &resp, argp, sizeof(resp));
+ if(err) {
+ pr_err("copy_from_user failed\n");
+ return -EINVAL;
+ }
- memcpy(&resp, argp, sizeof(resp));
this_lstnr = __qseecom_find_svc(data->listener.id);
if (this_lstnr == NULL)
return -EINVAL;
@@ -5508,10 +5580,19 @@ static int qseecom_get_qseos_version(struct qseecom_dev_handle *data,
void __user *argp)
{
struct qseecom_qseos_version_req req;
+ int err = 0;
- memcpy(&req, argp, sizeof(req));
+ K_COPY_FROM_USER(err, &req, argp, sizeof(req));
+ if(err) {
+ pr_err("copy_from_user failed\n");
+ return -EINVAL;
+ }
req.qseos_version = qseecom.qseos_version;
- memcpy(argp, &req, sizeof(req));
+ K_COPY_TO_USER(err, argp, &req, sizeof(req));
+ if(err) {
+ pr_err("copy_to_user failed\n");
+ return -EINVAL;
+ }
return 0;
}
@@ -5799,8 +5880,12 @@ static int qseecom_load_external_elf(struct qseecom_dev_handle *data,
void *va = NULL;
/* Copy the relevant information needed for loading the image */
- memcpy(&load_img_req, (void __user *)argp, sizeof(struct qseecom_load_img_req));
-
+ K_COPY_FROM_USER(ret, &load_img_req, argp,
+ sizeof(struct qseecom_load_img_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
/* Get the handle of the shared fd */
ret = qseecom_vaddr_map(load_img_req.ifd_data_fd, &pa, &va,
&sgt, &attach, &len, &dmabuf);
@@ -5965,8 +6050,13 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
bool found_app = false;
/* Copy the relevant information needed for loading the image */
- memcpy(&query_req, (void __user *)argp,
+ K_COPY_FROM_USER(ret, &query_req, argp,
sizeof(struct qseecom_qseos_app_load_query));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ ret = -EFAULT;
+ goto exit_free;
+ }
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0';
@@ -6039,7 +6129,12 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
spin_unlock_irqrestore(
&qseecom.registered_app_list_lock, flags);
}
- memcpy(argp, &query_req, sizeof(query_req));
+ K_COPY_TO_USER(ret, argp, &query_req, sizeof(query_req));
+ if(ret) {
+ pr_err("copy_to_user failed\n");
+ ret = -EFAULT;
+ goto exit_free;
+ }
ret = -EEXIST; /* app already loaded */
goto exit_free;
}
@@ -6439,9 +6534,13 @@ static int qseecom_create_key(struct qseecom_dev_handle *data,
struct qseecom_create_key_req create_key_req;
struct qseecom_key_generate_ireq generate_key_ireq;
struct qseecom_key_select_ireq set_key_ireq;
- uint32_t entries = 0;
+ int32_t entries = 0;
- memcpy(&create_key_req, argp, sizeof(create_key_req));
+ K_COPY_FROM_USER(ret, &create_key_req, argp, sizeof(create_key_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (create_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
create_key_req.usage >= QSEOS_KM_USAGE_MAX) {
pr_err("unsupported usage %d\n", create_key_req.usage);
@@ -6579,9 +6678,13 @@ static int qseecom_wipe_key(struct qseecom_dev_handle *data,
struct qseecom_wipe_key_req wipe_key_req;
struct qseecom_key_delete_ireq delete_key_ireq;
struct qseecom_key_select_ireq clear_key_ireq;
- uint32_t entries = 0;
+ int32_t entries = 0;
- memcpy(&wipe_key_req, argp, sizeof(wipe_key_req));
+ K_COPY_FROM_USER(ret, &wipe_key_req, argp, sizeof(wipe_key_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (wipe_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
wipe_key_req.usage >= QSEOS_KM_USAGE_MAX) {
@@ -6686,7 +6789,11 @@ static int qseecom_update_key_user_info(struct qseecom_dev_handle *data,
struct qseecom_update_key_userinfo_req update_key_req;
struct qseecom_key_userinfo_update_ireq ireq;
- memcpy(&update_key_req, argp, sizeof(update_key_req));
+ K_COPY_FROM_USER(ret, &update_key_req, argp, sizeof(update_key_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
if (update_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
update_key_req.usage >= QSEOS_KM_USAGE_MAX) {
@@ -6736,7 +6843,7 @@ static int qseecom_is_es_activated(void __user *argp)
{
struct qseecom_is_es_activated_req req = {0};
struct qseecom_command_scm_resp resp;
- int ret;
+ int ret = 0;
if (qseecom.qsee_version < QSEE_VERSION_04) {
pr_err("invalid qsee version\n");
@@ -6756,7 +6863,12 @@ static int qseecom_is_es_activated(void __user *argp)
}
req.is_activated = resp.result;
- memcpy(argp, &req, sizeof(req));
+ K_COPY_TO_USER(ret, argp, &req, sizeof(req));
+ if(ret) {
+ pr_err("copy_to_user failed\n");
+ return ret;
+ }
+
return 0;
}
@@ -6800,7 +6912,7 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
u32 tzbuflenin, tzbuflenout;
char *tzbufin = NULL, *tzbufout = NULL;
struct qseecom_scm_desc desc = {0};
- int ret;
+ int ret = 0;
phys_addr_t pain, paout;
struct qtee_shm shmin = {0}, shmout = {0};
@@ -6812,7 +6924,11 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
break;
}
- memcpy(&req, argp, sizeof(req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed, ret= %d\n", ret);
+ break;
+ }
if (req.in_buf == NULL || req.out_buf == NULL ||
req.in_buf_size == 0 || req.in_buf_size > MAX_DIP ||
@@ -6832,7 +6948,12 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
break;
}
- memcpy(tzbufin, (void __user *)req.in_buf, req.in_buf_size);
+ K_COPY_FROM_USER(ret, tzbufin, (void __user *)req.in_buf, req.in_buf_size);
+ if (ret) {
+ pr_err("copy_from_user failed, ret= %d\n", ret);
+ break;
+ }
+
qtee_shmbridge_flush_shm_buf(&shmin);
/* Prepare the output buffer in kernel space */
@@ -6870,7 +6991,11 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
/* Copy the output buffer from kernel space to userspace */
qtee_shmbridge_flush_shm_buf(&shmout);
- memcpy((void __user *)req.out_buf, tzbufout, req.out_buf_size);
+ K_COPY_TO_USER(ret, (void __user *)req.out_buf, tzbufout, req.out_buf_size);
+ if (ret) {
+ pr_err("copy_to_user failed, ret=%d\n", ret);
+ break;
+ }
} while (0);
__qseecom_free_tzbuf(&shmin);
@@ -7299,7 +7424,11 @@ static int qseecom_qteec_open_session(struct qseecom_dev_handle *data,
struct qseecom_qteec_modfd_req req;
int ret = 0;
- memcpy(&req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
ret = __qseecom_qteec_issue_cmd(data, (struct qseecom_qteec_req *)&req,
QSEOS_TEE_OPEN_SESSION);
@@ -7312,7 +7441,11 @@ static int qseecom_qteec_close_session(struct qseecom_dev_handle *data,
struct qseecom_qteec_req req;
int ret = 0;
- memcpy(&req, argp, sizeof(struct qseecom_qteec_req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(struct qseecom_qteec_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
ret = __qseecom_qteec_issue_cmd(data, &req, QSEOS_TEE_CLOSE_SESSION);
return ret;
}
@@ -7336,7 +7469,11 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data,
void *req_ptr = NULL;
void *resp_ptr = NULL;
- memcpy(&req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
ret = __qseecom_qteec_validate_msg(data,
(struct qseecom_qteec_req *)(&req));
if (ret)
@@ -7470,7 +7607,11 @@ static int qseecom_qteec_request_cancellation(struct qseecom_dev_handle *data,
struct qseecom_qteec_modfd_req req;
int ret = 0;
- memcpy(&req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ K_COPY_FROM_USER(ret, &req, argp, sizeof(struct qseecom_qteec_modfd_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
ret = __qseecom_qteec_issue_cmd(data, (struct qseecom_qteec_req *)&req,
QSEOS_TEE_REQUEST_CANCELLATION);
@@ -8190,7 +8331,11 @@ long qseecom_ioctl(struct file *file,
case QSEECOM_IOCTL_SET_ICE_INFO: {
struct qseecom_ice_data_t ice_data;
- memcpy(&ice_data, argp, sizeof(ice_data));
+ K_COPY_FROM_USER(ret, &ice_data, argp, sizeof(ice_data));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
qcom_ice_set_fde_flag(ice_data.flag);
break;
}
@@ -8315,7 +8460,7 @@ static const struct file_operations qseecom_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = qseecom_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = compat_qseecom_ioctl,
+ .compat_ioctl = qseecom_ioctl_32bit,
#endif
.open = qseecom_open,
.release = qseecom_release
@@ -8831,8 +8976,11 @@ static int qseecom_get_ce_info(struct qseecom_dev_handle *data,
bool found = false;
struct qseecom_ce_pipe_entry *pce_entry;
- memcpy(pinfo, argp, sizeof(struct qseecom_ce_info_req));
-
+ K_COPY_FROM_USER(ret, pinfo, argp, sizeof(struct qseecom_ce_info_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
switch (pinfo->usage) {
case QSEOS_KM_USAGE_DISK_ENCRYPTION:
case QSEOS_KM_USAGE_UFS_ICE_DISK_ENCRYPTION:
@@ -8893,7 +9041,11 @@ static int qseecom_get_ce_info(struct qseecom_dev_handle *data,
for (; i < MAX_CE_PIPE_PAIR_PER_UNIT; i++)
pinfo->ce_pipe_entry[i].valid = 0;
- memcpy(argp, pinfo, sizeof(struct qseecom_ce_info_req));
+ K_COPY_TO_USER(ret, argp, pinfo, sizeof(struct qseecom_ce_info_req));
+ if(ret) {
+ pr_err("copy_to_user failed\n");
+ ret = -EFAULT;
+ }
return ret;
}
@@ -8908,7 +9060,11 @@ static int qseecom_free_ce_info(struct qseecom_dev_handle *data,
int i;
bool found = false;
- memcpy(pinfo, argp, sizeof(struct qseecom_ce_info_req));
+ K_COPY_FROM_USER(ret, pinfo, argp, sizeof(struct qseecom_ce_info_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
switch (pinfo->usage) {
case QSEOS_KM_USAGE_DISK_ENCRYPTION:
@@ -8963,8 +9119,11 @@ static int qseecom_query_ce_info(struct qseecom_dev_handle *data,
bool found = false;
struct qseecom_ce_pipe_entry *pce_entry;
- memcpy(pinfo, argp, sizeof(struct qseecom_ce_info_req));
-
+ K_COPY_FROM_USER(ret, pinfo, argp, sizeof(struct qseecom_ce_info_req));
+ if(ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
switch (pinfo->usage) {
case QSEOS_KM_USAGE_DISK_ENCRYPTION:
case QSEOS_KM_USAGE_UFS_ICE_DISK_ENCRYPTION:
@@ -9022,7 +9181,11 @@ static int qseecom_query_ce_info(struct qseecom_dev_handle *data,
for (; i < MAX_CE_PIPE_PAIR_PER_UNIT; i++)
pinfo->ce_pipe_entry[i].valid = 0;
out:
- memcpy(argp, pinfo, sizeof(struct qseecom_ce_info_req));
+ K_COPY_TO_USER(ret, argp, pinfo, sizeof(struct qseecom_ce_info_req));
+ if(ret) {
+ pr_err("copy_to_user failed\n");
+ ret = -EFAULT;
+ }
return ret;
}
@@ -9308,6 +9471,7 @@ static int qseecom_init_control(void)
qseecom.qseos_version = QSEOS_VERSION_14;
qseecom.commonlib_loaded = false;
qseecom.commonlib64_loaded = false;
+ qseecom.commonlib_loaded_by_hostvm = false;
qseecom.whitelist_support = qseecom_check_whitelist_feature();
return rc;
@@ -9329,6 +9493,9 @@ static int qseecom_parse_dt(struct platform_device *pdev)
qseecom.commonlib64_loaded =
of_property_read_bool((&pdev->dev)->of_node,
"qcom,commonlib64-loaded-by-uefi");
+ qseecom.commonlib_loaded_by_hostvm =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,commonlib-loaded-by-hostvm");
qseecom.fde_key_size =
of_property_read_bool((&pdev->dev)->of_node,
"qcom,fde-key-size");
diff --git a/qseecom/qseecom_32bit_impl.c b/qseecom/qseecom_32bit_impl.c
new file mode 100644
index 0000000..71d208f
--- /dev/null
+++ b/qseecom/qseecom_32bit_impl.c
@@ -0,0 +1,943 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/qseecom.h>
+#include <linux/compat.h>
+#include <linux/mman.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/scatterlist.h>
+#include <linux/interconnect.h>
+#include <linux/delay.h>
+#include "qseecom_32bit_impl.h"
+
+
+static int get_qseecom_register_listener_req_32bit(
+ struct qseecom_register_listener_req_32bit __user *data32,
+ struct qseecom_register_listener_req *data)
+{
+ int err;
+ compat_ulong_t listener_id;
+ compat_long_t ifd_data_fd;
+ compat_uptr_t virt_sb_base;
+ compat_ulong_t sb_size;
+
+ err = get_user(listener_id, &data32->listener_id);
+ memcpy( &data->listener_id, &listener_id, sizeof(listener_id));
+ err |= get_user(ifd_data_fd, &data32->ifd_data_fd);
+ memcpy( &data->ifd_data_fd, &ifd_data_fd, sizeof(ifd_data_fd));
+ err |= get_user(virt_sb_base, &data32->virt_sb_base);
+ data->virt_sb_base = NULL;
+ memcpy(&data->virt_sb_base, &virt_sb_base, sizeof(virt_sb_base));
+ err |= get_user(sb_size, &data32->sb_size);
+ memcpy( &data->sb_size, &sb_size, sizeof(sb_size));
+ return err;
+}
+
+static int get_qseecom_load_img_req_32bit(
+ struct qseecom_load_img_req_32bit __user *data32,
+ struct qseecom_load_img_req *data)
+{
+ int err;
+ compat_ulong_t mdt_len;
+ compat_ulong_t img_len;
+ compat_long_t ifd_data_fd;
+ compat_ulong_t app_arch;
+ compat_uint_t app_id;
+ char img_name;
+ unsigned int i;
+
+ err = get_user(mdt_len, &data32->mdt_len);
+ memcpy( &data->mdt_len, &mdt_len, sizeof(mdt_len));
+ err |= get_user(img_len, &data32->img_len);
+ memcpy( &data->img_len, &img_len, sizeof(img_len));
+ err |= get_user(ifd_data_fd, &data32->ifd_data_fd);
+ memcpy( &data->ifd_data_fd, &ifd_data_fd, sizeof(ifd_data_fd));
+ for (i = 0; i < MAX_APP_NAME_SIZE; i++) {
+ err |= get_user(img_name, &(data32->img_name[i]));
+ memcpy( &data->img_name[i], &img_name, sizeof(img_name));
+ }
+ err |= get_user(app_arch, &data32->app_arch);
+ memcpy( &data->app_arch, &app_arch, sizeof(app_arch));
+ err |= get_user(app_id, &data32->app_id);
+ memcpy( &data->app_id, &app_id, sizeof(app_id));
+ return err;
+}
+
+static int get_qseecom_send_cmd_req_32bit(
+ struct qseecom_send_cmd_req_32bit __user *data32,
+ struct qseecom_send_cmd_req *data)
+{
+ int err;
+ compat_uptr_t cmd_req_buf;
+ compat_uint_t cmd_req_len;
+ compat_uptr_t resp_buf;
+ compat_uint_t resp_len;
+
+ err = get_user(cmd_req_buf, &data32->cmd_req_buf);
+ data->cmd_req_buf = NULL;
+ memcpy( &data->cmd_req_buf, &cmd_req_buf, sizeof(cmd_req_buf));
+ err |= get_user(cmd_req_len, &data32->cmd_req_len);
+ memcpy( &data->cmd_req_len, &cmd_req_len, sizeof(cmd_req_len));
+ err |= get_user(resp_buf, &data32->resp_buf);
+ data->resp_buf = NULL;
+ memcpy( &data->resp_buf, &resp_buf, sizeof(resp_buf));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy( &data->resp_len, &resp_len, sizeof(resp_len));
+ return err;
+}
+
+static int get_qseecom_send_modfd_cmd_req_32bit(
+ struct qseecom_send_modfd_cmd_req_32bit __user *data32,
+ struct qseecom_send_modfd_cmd_req *data)
+{
+ int err;
+ unsigned int i;
+ compat_uptr_t cmd_req_buf;
+ compat_uint_t cmd_req_len;
+ compat_uptr_t resp_buf;
+ compat_uint_t resp_len;
+ compat_long_t fd;
+ compat_ulong_t cmd_buf_offset;
+
+ err = get_user(cmd_req_buf, &data32->cmd_req_buf);
+ data->cmd_req_buf = NULL;
+ memcpy( &data->cmd_req_buf, &cmd_req_buf, sizeof(cmd_req_buf));
+ err |= get_user(cmd_req_len, &data32->cmd_req_len);
+ memcpy(&data->cmd_req_len, &cmd_req_len, sizeof(cmd_req_len));
+ err |= get_user(resp_buf, &data32->resp_buf);
+ data->resp_buf = NULL;
+ memcpy(&data->resp_buf, &resp_buf, sizeof(resp_buf));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy( &data->resp_len, &resp_len, sizeof(resp_len));
+ for (i = 0; i < MAX_ION_FD; i++) {
+ err |= get_user(fd, &data32->ifd_data[i].fd);
+ memcpy(&data->ifd_data[i].fd, &fd, sizeof(fd));
+ err |= get_user(cmd_buf_offset,
+ &data32->ifd_data[i].cmd_buf_offset);
+ memcpy(&data->ifd_data[i].cmd_buf_offset, &cmd_buf_offset, sizeof(cmd_buf_offset));
+ }
+ return err;
+}
+
+static int get_qseecom_set_sb_mem_param_req_32bit(
+ struct qseecom_set_sb_mem_param_req_32bit __user *data32,
+ struct qseecom_set_sb_mem_param_req *data)
+{
+ int err;
+ compat_long_t ifd_data_fd;
+ compat_uptr_t virt_sb_base;
+ compat_ulong_t sb_len;
+
+ err = get_user(ifd_data_fd, &data32->ifd_data_fd);
+ memcpy(&data->ifd_data_fd, &ifd_data_fd, sizeof(ifd_data_fd));
+ err |= get_user(virt_sb_base, &data32->virt_sb_base);
+ data->virt_sb_base = NULL;
+ memcpy(&data->virt_sb_base, &virt_sb_base, sizeof(virt_sb_base));
+ err |= get_user(sb_len, &data32->sb_len);
+ memcpy(&data->sb_len, &sb_len, sizeof(sb_len));
+ return err;
+}
+
+static int get_qseecom_qseos_version_req_32bit(
+ struct qseecom_qseos_version_req_32bit __user *data32,
+ struct qseecom_qseos_version_req *data)
+{
+ int err;
+ compat_uint_t qseos_version;
+
+ err = get_user(qseos_version, &data32->qseos_version);
+ memcpy( &data->qseos_version, &qseos_version, sizeof(qseos_version));
+ return err;
+}
+
+static int get_qseecom_qseos_app_load_query_32bit(
+ struct qseecom_qseos_app_load_query_32bit __user *data32,
+ struct qseecom_qseos_app_load_query *data)
+{
+ int err = 0;
+ unsigned int i;
+ compat_uint_t app_id;
+ char app_name;
+ compat_ulong_t app_arch;
+
+ for (i = 0; i < MAX_APP_NAME_SIZE; i++) {
+ err |= get_user(app_name, &(data32->app_name[i]));
+ memcpy(&data->app_name[i], &app_name, sizeof(app_name));
+ }
+ err |= get_user(app_id, &data32->app_id);
+ memcpy(&data->app_id, &app_id, sizeof(app_id));
+ err |= get_user(app_arch, &data32->app_arch);
+ memcpy(&data->app_arch, &app_arch, sizeof(app_arch));
+ return err;
+}
+
+static int get_qseecom_send_svc_cmd_req_32bit(
+ struct qseecom_send_svc_cmd_req_32bit __user *data32,
+ struct qseecom_send_svc_cmd_req *data)
+{
+ int err;
+ compat_ulong_t cmd_id;
+ compat_uptr_t cmd_req_buf;
+ compat_uint_t cmd_req_len;
+ compat_uptr_t resp_buf;
+ compat_uint_t resp_len;
+
+ err = get_user(cmd_id, &data32->cmd_id);
+ memcpy(&data->cmd_id, &cmd_id, sizeof(cmd_id));
+ err |= get_user(cmd_req_buf, &data32->cmd_req_buf);
+ data->cmd_req_buf = NULL;
+ memcpy(&data->cmd_req_buf, &cmd_req_buf, sizeof(cmd_req_buf));
+ err |= get_user(cmd_req_len, &data32->cmd_req_len);
+ memcpy(&data->cmd_req_len, &cmd_req_len, sizeof(cmd_req_len));
+ err |= get_user(resp_buf, &data32->resp_buf);
+ data->resp_buf = NULL;
+ memcpy(&data->resp_buf, &resp_buf, sizeof(resp_buf));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy(&data->resp_len, &resp_len, sizeof(resp_len));
+ return err;
+}
+
+static int get_qseecom_create_key_req_32bit(
+ struct qseecom_create_key_req_32bit __user *data32,
+ struct qseecom_create_key_req *data)
+{
+ int err = 0;
+ compat_uint_t usage;
+ unsigned char hash32;
+ unsigned int i;
+
+ for (i = 0; i < QSEECOM_HASH_SIZE; i++) {
+ err |= get_user(hash32, &(data32->hash32[i]));
+ memcpy( &data->hash32[i], &hash32, sizeof(hash32));
+ }
+ err = get_user(usage, &data32->usage);
+ memcpy(&data->usage, &usage, sizeof(usage));
+
+ return err;
+}
+
+static int get_qseecom_wipe_key_req_32bit(
+ struct qseecom_wipe_key_req_32bit __user *data32,
+ struct qseecom_wipe_key_req *data)
+{
+ int err;
+ compat_uint_t usage;
+ compat_int_t wipe_key_flag;
+
+ err = get_user(usage, &data32->usage);
+ memcpy(&data->usage, &usage, sizeof(usage));
+ err |= get_user(wipe_key_flag, &data32->wipe_key_flag);
+ memcpy(&data->wipe_key_flag, &wipe_key_flag, sizeof(wipe_key_flag));
+
+ return err;
+}
+
+static int get_qseecom_update_key_userinfo_req_32bit(
+ struct qseecom_update_key_userinfo_req_32bit __user *data32,
+ struct qseecom_update_key_userinfo_req *data)
+{
+ int err = 0;
+ compat_uint_t usage;
+ unsigned char current_hash32;
+ unsigned char new_hash32;
+ unsigned int i;
+
+ for (i = 0; i < QSEECOM_HASH_SIZE; i++) {
+ err |= get_user(current_hash32, &(data32->current_hash32[i]));
+ memcpy( &data->current_hash32[i], &current_hash32, sizeof(current_hash32));
+ }
+ for (i = 0; i < QSEECOM_HASH_SIZE; i++) {
+ err |= get_user(new_hash32, &(data32->new_hash32[i]));
+ memcpy( &data->new_hash32[i], &new_hash32, sizeof(new_hash32));
+ }
+ err = get_user(usage, &data32->usage);
+ memcpy(&data->usage, &usage, sizeof(usage));
+
+ return err;
+}
+
+static int get_qseecom_save_partition_hash_req_32bit(
+ struct qseecom_save_partition_hash_req_32bit __user *data32,
+ struct qseecom_save_partition_hash_req *data)
+{
+ int err;
+ compat_int_t partition_id;
+ char digest;
+ unsigned int i;
+
+ err = get_user(partition_id, &data32->partition_id);
+ memcpy(&data->partition_id, &partition_id, sizeof(partition_id));
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+ err |= get_user(digest, &(data32->digest[i]));
+ memcpy( &data->digest[i], &digest, sizeof(digest));
+ }
+ return err;
+}
+
+static int get_qseecom_is_es_activated_req_32bit(
+ struct qseecom_is_es_activated_req_32bit __user *data32,
+ struct qseecom_is_es_activated_req *data)
+{
+ compat_int_t is_activated;
+ int err;
+
+ err = get_user(is_activated, &data32->is_activated);
+ memcpy(&data->is_activated, &is_activated, sizeof(is_activated));
+ return err;
+}
+
+static int get_qseecom_mdtp_cipher_dip_req_32bit(
+ struct qseecom_mdtp_cipher_dip_req_32bit __user *data32,
+ struct qseecom_mdtp_cipher_dip_req *data)
+{
+ int err;
+ compat_int_t in_buf_size;
+ compat_uptr_t in_buf;
+ compat_int_t out_buf_size;
+ compat_uptr_t out_buf;
+ compat_int_t direction;
+
+ err = get_user(in_buf_size, &data32->in_buf_size);
+ memcpy(&data->in_buf_size, &in_buf_size, sizeof(in_buf_size));
+ err |= get_user(out_buf_size, &data32->out_buf_size);
+ memcpy(&data->out_buf_size, &out_buf_size, sizeof(out_buf_size));
+ err |= get_user(direction, &data32->direction);
+ memcpy(&data->direction, &direction, sizeof(direction));
+ err |= get_user(in_buf, &data32->in_buf);
+ data->in_buf = NULL;
+ memcpy(&data->in_buf, &in_buf, sizeof(in_buf));
+ err |= get_user(out_buf, &data32->out_buf);
+ data->out_buf = NULL;
+ memcpy(&data->out_buf, &out_buf, sizeof(out_buf));
+
+ return err;
+}
+
+static int get_qseecom_send_modfd_listener_resp_32bit(
+ struct qseecom_send_modfd_listener_resp_32bit __user *data32,
+ struct qseecom_send_modfd_listener_resp *data)
+{
+ int err;
+ unsigned int i;
+ compat_uptr_t resp_buf_ptr;
+ compat_uint_t resp_len;
+ compat_long_t fd;
+ compat_ulong_t cmd_buf_offset;
+
+ err = get_user(resp_buf_ptr, &data32->resp_buf_ptr);
+ data->resp_buf_ptr = NULL;
+ memcpy(&data->resp_buf_ptr, &resp_buf_ptr, sizeof(resp_buf_ptr));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy(&data->resp_len, &resp_len, sizeof(resp_len));
+ for (i = 0; i < MAX_ION_FD; i++) {
+ err |= get_user(fd, &data32->ifd_data[i].fd);
+ memcpy(&data->ifd_data[i].fd, &fd, sizeof(fd));
+ err |= get_user(cmd_buf_offset,
+ &data32->ifd_data[i].cmd_buf_offset);
+ memcpy(&data->ifd_data[i].cmd_buf_offset, &cmd_buf_offset, sizeof(cmd_buf_offset));
+ }
+ return err;
+}
+
+
+static int get_qseecom_qteec_req_32bit(
+ struct qseecom_qteec_req_32bit __user *data32,
+ struct qseecom_qteec_req *data)
+{
+ compat_uptr_t req_ptr;
+ compat_ulong_t req_len;
+ compat_uptr_t resp_ptr;
+ compat_ulong_t resp_len;
+ int err;
+
+ err = get_user(req_ptr, &data32->req_ptr);
+ data->req_ptr = NULL;
+ memcpy(&data->req_ptr, &req_ptr, sizeof(req_ptr));
+ err |= get_user(req_len, &data32->req_len);
+ memcpy(&data->req_len, &req_len, sizeof(req_len));
+ err |= get_user(resp_ptr, &data32->resp_ptr);
+ data->resp_ptr = NULL;
+ memcpy(&data->resp_ptr, &resp_ptr, sizeof(resp_ptr));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy(&data->resp_len, &resp_len, sizeof(resp_len));
+ return err;
+}
+
+static int get_qseecom_qteec_modfd_req_32bit(
+ struct qseecom_qteec_modfd_req_32bit __user *data32,
+ struct qseecom_qteec_modfd_req *data)
+{
+ compat_uptr_t req_ptr;
+ compat_ulong_t req_len;
+ compat_uptr_t resp_ptr;
+ compat_ulong_t resp_len;
+ compat_long_t fd;
+ compat_ulong_t cmd_buf_offset;
+ int err, i;
+
+ err = get_user(req_ptr, &data32->req_ptr);
+ data->req_ptr = NULL;
+ memcpy(&data->req_ptr, &req_ptr, sizeof(req_ptr));
+ err |= get_user(req_len, &data32->req_len);
+ memcpy(&data->req_len, &req_len, sizeof(req_len));
+
+ err |= get_user(resp_ptr, &data32->resp_ptr);
+ data->resp_ptr = NULL;
+ memcpy(&data->resp_ptr, &resp_ptr, sizeof(resp_ptr));
+ err |= get_user(resp_len, &data32->resp_len);
+ memcpy(&data->resp_len, &resp_len, sizeof(resp_len));
+
+ for (i = 0; i < MAX_ION_FD; i++) {
+ err |= get_user(fd, &data32->ifd_data[i].fd);
+ memcpy(&data->ifd_data[i].fd, &fd, sizeof(fd));
+ err |= get_user(cmd_buf_offset,
+ &data32->ifd_data[i].cmd_buf_offset);
+ memcpy(&data->ifd_data[i].cmd_buf_offset, &cmd_buf_offset, sizeof(cmd_buf_offset));
+ }
+ return err;
+}
+
+static int get_int_32bit(compat_int_t __user *data32,
+ int *data)
+{
+ compat_int_t x;
+ int err;
+
+ err = get_user(x, data32);
+ memcpy(&data, &x, sizeof(x));
+ return err;
+}
+
+static int put_qseecom_load_img_req_32bit(
+ struct qseecom_load_img_req_32bit __user *data32,
+ struct qseecom_load_img_req *data)
+{
+ int err;
+ compat_ulong_t mdt_len;
+ compat_ulong_t img_len;
+ compat_long_t ifd_data_fd;
+ compat_ulong_t app_arch;
+ compat_int_t app_id;
+ char img_name;
+ unsigned int i;
+
+ memcpy(&mdt_len, &data->mdt_len, sizeof(mdt_len));
+ err = put_user(mdt_len, &data32->mdt_len);
+ memcpy(&img_len, &data->img_len, sizeof(img_len));
+ err |= put_user(img_len, &data32->img_len);
+ memcpy(&ifd_data_fd, &data->ifd_data_fd, sizeof(ifd_data_fd));
+ err |= put_user(ifd_data_fd, &data32->ifd_data_fd);
+ for (i = 0; i < MAX_APP_NAME_SIZE; i++) {
+ memcpy(&img_name, &data->img_name[i], sizeof(img_name));
+ err |= put_user(img_name, &data32->img_name[i]);
+ }
+ memcpy(&app_arch, &data->app_arch, sizeof(app_arch));
+ err |= put_user(app_arch, &data32->app_arch);
+ memcpy(&app_id, &data->app_id, sizeof(app_id));
+ err |= put_user(app_id, &data32->app_id);
+ return err;
+}
+
+static int put_qseecom_qseos_version_req_32bit(
+ struct qseecom_qseos_version_req_32bit __user *data32,
+ struct qseecom_qseos_version_req *data)
+{
+ compat_uint_t qseos_version;
+ int err;
+ memcpy(&qseos_version, &data->qseos_version, sizeof(qseos_version));
+ err = put_user(qseos_version, &data32->qseos_version);
+ return err;
+}
+
+static int put_qseecom_qseos_app_load_query_32bit(
+ struct qseecom_qseos_app_load_query_32bit __user *data32,
+ struct qseecom_qseos_app_load_query *data)
+{
+ int err = 0;
+ unsigned int i;
+ compat_int_t app_id;
+ compat_ulong_t app_arch;
+ char app_name;
+
+ for (i = 0; i < MAX_APP_NAME_SIZE; i++) {
+ memcpy(&app_name, &data->app_name[i], sizeof(app_name));
+ err |= put_user(app_name, &(data32->app_name[i]));
+ }
+ memcpy(&app_id, &data->app_id, sizeof(app_id));
+ err |= put_user(app_id, &data32->app_id);
+ memcpy(&app_arch, &data->app_arch, sizeof(app_arch));
+ err |= put_user(app_arch, &data32->app_arch);
+
+ return err;
+}
+
+static int put_qseecom_is_es_activated_req_32bit(
+ struct qseecom_is_es_activated_req_32bit __user *data32,
+ struct qseecom_is_es_activated_req *data)
+{
+ compat_int_t is_activated;
+ int err;
+
+ memcpy(&is_activated, &data->is_activated, sizeof(is_activated));
+ err = put_user(is_activated, &data32->is_activated);
+ return err;
+}
+
+static unsigned int convert_cmd(unsigned int cmd)
+{
+ switch (cmd) {
+ case QSEECOM_IOCTL_REGISTER_LISTENER_REQ_32BIT:
+ return QSEECOM_IOCTL_REGISTER_LISTENER_REQ;
+ case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ_32BIT:
+ return QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ;
+ case QSEECOM_IOCTL_LOAD_APP_REQ_32BIT:
+ return QSEECOM_IOCTL_LOAD_APP_REQ;
+ case QSEECOM_IOCTL_RECEIVE_REQ_32BIT:
+ return QSEECOM_IOCTL_RECEIVE_REQ;
+ case QSEECOM_IOCTL_SEND_RESP_REQ_32BIT:
+ return QSEECOM_IOCTL_SEND_RESP_REQ;
+ case QSEECOM_IOCTL_UNLOAD_APP_REQ_32BIT:
+ return QSEECOM_IOCTL_UNLOAD_APP_REQ;
+ case QSEECOM_IOCTL_PERF_ENABLE_REQ_32BIT:
+ return QSEECOM_IOCTL_PERF_ENABLE_REQ;
+ case QSEECOM_IOCTL_PERF_DISABLE_REQ_32BIT:
+ return QSEECOM_IOCTL_PERF_DISABLE_REQ;
+ case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ_32BIT:
+ return QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ;
+ case QSEECOM_IOCTL_SET_BUS_SCALING_REQ_32BIT:
+ return QSEECOM_IOCTL_SET_BUS_SCALING_REQ;
+ case QSEECOM_IOCTL_SEND_CMD_REQ_32BIT:
+ return QSEECOM_IOCTL_SEND_CMD_REQ;
+ case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ_32BIT:
+ return QSEECOM_IOCTL_SEND_MODFD_CMD_REQ;
+ case QSEECOM_IOCTL_SET_MEM_PARAM_REQ_32BIT:
+ return QSEECOM_IOCTL_SET_MEM_PARAM_REQ;
+ case QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ_32BIT:
+ return QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ;
+ case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ_32BIT:
+ return QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ;
+ case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ_32BIT:
+ return QSEECOM_IOCTL_APP_LOADED_QUERY_REQ;
+ case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ_32BIT:
+ return QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ;
+ case QSEECOM_IOCTL_CREATE_KEY_REQ_32BIT:
+ return QSEECOM_IOCTL_CREATE_KEY_REQ;
+ case QSEECOM_IOCTL_WIPE_KEY_REQ_32BIT:
+ return QSEECOM_IOCTL_WIPE_KEY_REQ;
+ case QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ_32BIT:
+ return QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ;
+ case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ_32BIT:
+ return QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ;
+ case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ_32BIT:
+ return QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ;
+ case QSEECOM_IOCTL_SEND_MODFD_RESP_32BIT:
+ return QSEECOM_IOCTL_SEND_MODFD_RESP;
+ case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ_32BIT:
+ return QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ;
+ case QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ_32BIT:
+ return QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ;
+ case QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ_32BIT:
+ return QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ;
+ case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ_32BIT:
+ return QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ;
+ case QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ_32BIT:
+ return QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ;
+ case QSEECOM_IOCTL_SEND_MODFD_CMD_64_REQ_32BIT:
+ return QSEECOM_IOCTL_SEND_MODFD_CMD_64_REQ;
+ case QSEECOM_IOCTL_SEND_MODFD_RESP_64_32BIT:
+ return QSEECOM_IOCTL_SEND_MODFD_RESP_64;
+
+ default:
+ return cmd;
+ }
+}
+
+long qseecom_ioctl_32bit(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ switch (cmd) {
+
+ case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ_32BIT:
+ case QSEECOM_IOCTL_RECEIVE_REQ_32BIT:
+ case QSEECOM_IOCTL_SEND_RESP_REQ_32BIT:
+ case QSEECOM_IOCTL_UNLOAD_APP_REQ_32BIT:
+ case QSEECOM_IOCTL_PERF_ENABLE_REQ_32BIT:
+ case QSEECOM_IOCTL_PERF_DISABLE_REQ_32BIT:
+ case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ_32BIT: {
+ return qseecom_ioctl(file, convert_cmd(cmd), 0);
+ }
+ break;
+ case QSEECOM_IOCTL_REGISTER_LISTENER_REQ_32BIT: {
+ struct qseecom_register_listener_req_32bit __user *data32;
+ struct qseecom_register_listener_req *data;
+ int err;
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_register_listener_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_LOAD_APP_REQ_32BIT: {
+ struct qseecom_load_img_req_32bit __user *data32;
+ struct qseecom_load_img_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+ err = get_qseecom_load_img_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ ret = qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ err = put_qseecom_load_img_req_32bit(data32, data);
+ return ret ? ret : err;
+ }
+ break;
+ case QSEECOM_IOCTL_SEND_CMD_REQ_32BIT: {
+ struct qseecom_send_cmd_req_32bit __user *data32;
+ struct qseecom_send_cmd_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_send_cmd_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ_32BIT:
+ case QSEECOM_IOCTL_SEND_MODFD_CMD_64_REQ_32BIT: {
+ struct qseecom_send_modfd_cmd_req_32bit __user *data32;
+ struct qseecom_send_modfd_cmd_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_send_modfd_cmd_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_SET_MEM_PARAM_REQ_32BIT: {
+ struct qseecom_set_sb_mem_param_req_32bit __user *data32;
+ struct qseecom_set_sb_mem_param_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_set_sb_mem_param_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ_32BIT: {
+ struct qseecom_qseos_version_req_32bit __user *data32;
+ struct qseecom_qseos_version_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_qseos_version_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ ret = qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ err = put_qseecom_qseos_version_req_32bit(data32, data);
+
+ return ret ? ret : err;
+ }
+ break;
+ case QSEECOM_IOCTL_SET_BUS_SCALING_REQ_32BIT: {
+ compat_int_t __user *data32;
+ int *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+ err = get_int_32bit(data32, data);
+ if (err)
+ return err;
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ_32BIT: {
+ struct qseecom_load_img_req_32bit __user *data32;
+ struct qseecom_load_img_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_load_img_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ_32BIT: {
+ struct qseecom_qseos_app_load_query_32bit __user *data32;
+ struct qseecom_qseos_app_load_query *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_qseos_app_load_query_32bit(data32, data);
+ if (err)
+ return err;
+
+ ret = qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ err = put_qseecom_qseos_app_load_query_32bit(data32, data);
+ return ret ? ret : err;
+ }
+ break;
+ case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ_32BIT: {
+ struct qseecom_send_svc_cmd_req_32bit __user *data32;
+ struct qseecom_send_svc_cmd_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_send_svc_cmd_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_CREATE_KEY_REQ_32BIT: {
+ struct qseecom_create_key_req_32bit __user *data32;
+ struct qseecom_create_key_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_create_key_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_WIPE_KEY_REQ_32BIT: {
+ struct qseecom_wipe_key_req_32bit __user *data32;
+ struct qseecom_wipe_key_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_wipe_key_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ_32BIT: {
+ struct qseecom_update_key_userinfo_req_32bit __user *data32;
+ struct qseecom_update_key_userinfo_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_update_key_userinfo_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ_32BIT: {
+ struct qseecom_save_partition_hash_req_32bit __user *data32;
+ struct qseecom_save_partition_hash_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_save_partition_hash_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ_32BIT: {
+ struct qseecom_is_es_activated_req_32bit __user *data32;
+ struct qseecom_is_es_activated_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_is_es_activated_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ ret = qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ err = put_qseecom_is_es_activated_req_32bit(data32, data);
+ return ret ? ret : err;
+ }
+ break;
+ case QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ_32BIT: {
+ struct qseecom_mdtp_cipher_dip_req_32bit __user *data32;
+ struct qseecom_mdtp_cipher_dip_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_mdtp_cipher_dip_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_IOCTL_SEND_MODFD_RESP_32BIT:
+ case QSEECOM_IOCTL_SEND_MODFD_RESP_64_32BIT: {
+ struct qseecom_send_modfd_listener_resp_32bit __user *data32;
+ struct qseecom_send_modfd_listener_resp *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_send_modfd_listener_resp_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ_32BIT: {
+ struct qseecom_qteec_req_32bit __user *data32;
+ struct qseecom_qteec_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_qteec_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ_32BIT:
+ case QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ_32BIT:
+ case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ_32BIT: {
+ struct qseecom_qteec_modfd_req_32bit __user *data32;
+ struct qseecom_qteec_modfd_req *data;
+ int err;
+
+ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -EFAULT;
+
+ err = get_qseecom_qteec_modfd_req_32bit(data32, data);
+ if (err)
+ return err;
+
+ return qseecom_ioctl(file, convert_cmd(cmd),
+ (unsigned long)data);
+ }
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ break;
+ }
+ return 0;
+}
diff --git a/qseecom/qseecom_32bit_impl.h b/qseecom/qseecom_32bit_impl.h
new file mode 100644
index 0000000..068a49b
--- /dev/null
+++ b/qseecom/qseecom_32bit_impl.h
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2017, 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef _UAPI_COMPAT_QSEECOM_H_
+#define _UAPI_COMPAT_QSEECOM_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#if IS_ENABLED(CONFIG_COMPAT)
+#include <linux/compat.h>
+
+/*
+ * struct qseecom_register_listener_req_32bit -
+ * for register listener ioctl request
+ * @listener_id - service id (shared between userspace and QSE)
+ * @ifd_data_fd - ion handle
+ * @virt_sb_base - shared buffer base in user space
+ * @sb_size - shared buffer size
+ */
+struct qseecom_register_listener_req_32bit {
+ compat_ulong_t listener_id; /* in */
+ compat_long_t ifd_data_fd; /* in */
+ compat_uptr_t virt_sb_base; /* in */
+ compat_ulong_t sb_size; /* in */
+};
+
+/*
+ * struct qseecom_send_cmd_req_32bit - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ */
+struct qseecom_send_cmd_req_32bit {
+ compat_uptr_t cmd_req_buf; /* in */
+ compat_uint_t cmd_req_len; /* in */
+ compat_uptr_t resp_buf; /* in/out */
+ compat_uint_t resp_len; /* in/out */
+};
+
+/*
+ * struct qseecom_ion_fd_info_32bit - ion fd handle data information
+ * @fd - ion handle to some memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_ion_fd_info_32bit {
+ compat_long_t fd;
+ compat_ulong_t cmd_buf_offset;
+};
+/*
+ * struct qseecom_send_modfd_cmd_req_32bit - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ * @ifd_data_fd - ion handle to memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_send_modfd_cmd_req_32bit {
+ compat_uptr_t cmd_req_buf; /* in */
+ compat_uint_t cmd_req_len; /* in */
+ compat_uptr_t resp_buf; /* in/out */
+ compat_uint_t resp_len; /* in/out */
+ struct qseecom_ion_fd_info_32bit ifd_data[MAX_ION_FD];
+};
+
+/*
+ * struct qseecom_listener_send_resp_req_32bit
+ * signal to continue the send_cmd req.
+ * Used as a trigger from HLOS service to notify QSEECOM that it's done with its
+ * operation and provide the response for QSEECOM can continue the incomplete
+ * command execution
+ * @resp_len - Length of the response
+ * @resp_buf - Response buffer where the response of the cmd should go.
+ */
+struct qseecom_send_resp_req_32bit {
+ compat_uptr_t resp_buf; /* in */
+ compat_uint_t resp_len; /* in */
+};
+
+/*
+ * struct qseecom_load_img_data_32bit
+ * for sending image length information and
+ * ion file descriptor to the qseecom driver. ion file descriptor is used
+ * for retrieving the ion file handle and in turn the physical address of
+ * the image location.
+ * @mdt_len - Length of the .mdt file in bytes.
+ * @img_len - Length of the .mdt + .b00 +..+.bxx images files in bytes
+ * @ion_fd - Ion file descriptor used when allocating memory.
+ * @img_name - Name of the image.
+ */
+struct qseecom_load_img_req_32bit {
+ compat_ulong_t mdt_len; /* in */
+ compat_ulong_t img_len; /* in */
+ compat_long_t ifd_data_fd; /* in */
+ char img_name[MAX_APP_NAME_SIZE]; /* in */
+ compat_ulong_t app_arch; /* in */
+ compat_uint_t app_id; /* out*/
+};
+
+struct qseecom_set_sb_mem_param_req_32bit {
+ compat_long_t ifd_data_fd; /* in */
+ compat_uptr_t virt_sb_base; /* in */
+ compat_ulong_t sb_len; /* in */
+};
+
+/*
+ * struct qseecom_qseos_version_req_32bit - get qseos version
+ * @qseos_version - version number
+ */
+struct qseecom_qseos_version_req_32bit {
+ compat_uint_t qseos_version; /* in */
+};
+
+/*
+ * struct qseecom_qseos_app_load_query_32bit - verify if app is loaded in qsee
+ * @app_name[MAX_APP_NAME_SIZE]- name of the app.
+ * @app_id - app id.
+ */
+struct qseecom_qseos_app_load_query_32bit {
+ char app_name[MAX_APP_NAME_SIZE]; /* in */
+ compat_uint_t app_id; /* out */
+ compat_ulong_t app_arch;
+};
+
+struct qseecom_send_svc_cmd_req_32bit {
+ compat_ulong_t cmd_id;
+ compat_uptr_t cmd_req_buf; /* in */
+ compat_uint_t cmd_req_len; /* in */
+ compat_uptr_t resp_buf; /* in/out */
+ compat_uint_t resp_len; /* in/out */
+};
+
+struct qseecom_create_key_req_32bit {
+ unsigned char hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_key_management_usage_type usage;
+};
+
+struct qseecom_wipe_key_req_32bit {
+ enum qseecom_key_management_usage_type usage;
+ compat_int_t wipe_key_flag;
+};
+
+struct qseecom_update_key_userinfo_req_32bit {
+ unsigned char current_hash32[QSEECOM_HASH_SIZE];
+ unsigned char new_hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_key_management_usage_type usage;
+};
+
+/*
+ * struct qseecom_save_partition_hash_req_32bit
+ * @partition_id - partition id.
+ * @hash[SHA256_DIGEST_LENGTH] - sha256 digest.
+ */
+struct qseecom_save_partition_hash_req_32bit {
+ compat_int_t partition_id; /* in */
+ char digest[SHA256_DIGEST_LENGTH]; /* in */
+};
+
+/*
+ * struct qseecom_is_es_activated_req_32bit
+ * @is_activated - 1=true , 0=false
+ */
+struct qseecom_is_es_activated_req_32bit {
+ compat_int_t is_activated; /* out */
+};
+
+/*
+ * struct qseecom_mdtp_cipher_dip_req_32bit
+ * @in_buf - input buffer
+ * @in_buf_size - input buffer size
+ * @out_buf - output buffer
+ * @out_buf_size - output buffer size
+ * @direction - 0=encrypt, 1=decrypt
+ */
+struct qseecom_mdtp_cipher_dip_req_32bit {
+ compat_uptr_t in_buf;
+ compat_uint_t in_buf_size;
+ compat_uptr_t out_buf;
+ compat_uint_t out_buf_size;
+ compat_uint_t direction;
+};
+
+/*
+ * struct qseecom_send_modfd_resp_32bit - for send command ioctl request
+ * @req_len - command buffer length
+ * @req_buf - command buffer
+ * @ifd_data_fd - ion handle to memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_send_modfd_listener_resp_32bit {
+ compat_uptr_t resp_buf_ptr; /* in */
+ compat_uint_t resp_len; /* in */
+ struct qseecom_ion_fd_info_32bit ifd_data[MAX_ION_FD]; /* in */
+};
+
+struct qseecom_qteec_req_32bit {
+ compat_uptr_t req_ptr;
+ compat_ulong_t req_len;
+ compat_uptr_t resp_ptr;
+ compat_ulong_t resp_len;
+};
+
+struct qseecom_qteec_modfd_req_32bit {
+ compat_uptr_t req_ptr;
+ compat_ulong_t req_len;
+ compat_uptr_t resp_ptr;
+ compat_ulong_t resp_len;
+ struct qseecom_ion_fd_info_32bit ifd_data[MAX_ION_FD];
+};
+
+struct qseecom_ce_pipe_entry_32bit {
+ compat_int_t valid;
+ compat_uint_t ce_num;
+ compat_uint_t ce_pipe_pair;
+};
+
+struct ce_info_req_32bit {
+ unsigned char handle[MAX_CE_INFO_HANDLE_SIZE];
+ compat_uint_t usage;
+ compat_uint_t unit_num;
+ compat_uint_t num_ce_pipe_entries;
+ struct qseecom_ce_pipe_entry_32bit
+ ce_pipe_entry[MAX_CE_PIPE_PAIR_PER_UNIT];
+};
+
+struct file;
+extern long qseecom_ioctl_32bit(struct file *file,
+ unsigned int cmd, unsigned long arg);
+
+extern long qseecom_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg);
+
+#define QSEECOM_IOCTL_REGISTER_LISTENER_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 1, struct qseecom_register_listener_req_32bit)
+
+#define QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 2)
+
+#define QSEECOM_IOCTL_SEND_CMD_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 3, struct qseecom_send_cmd_req_32bit)
+
+#define QSEECOM_IOCTL_SEND_MODFD_CMD_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 4, struct qseecom_send_modfd_cmd_req_32bit)
+
+#define QSEECOM_IOCTL_RECEIVE_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 5)
+
+#define QSEECOM_IOCTL_SEND_RESP_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 6)
+
+#define QSEECOM_IOCTL_LOAD_APP_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 7, struct qseecom_load_img_req_32bit)
+
+#define QSEECOM_IOCTL_SET_MEM_PARAM_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 8, struct qseecom_set_sb_mem_param_req_32bit)
+
+#define QSEECOM_IOCTL_UNLOAD_APP_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 9)
+
+#define QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 10, struct qseecom_qseos_version_req_32bit)
+
+#define QSEECOM_IOCTL_PERF_ENABLE_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 11)
+
+#define QSEECOM_IOCTL_PERF_DISABLE_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 12)
+
+#define QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 13, struct qseecom_load_img_req_32bit)
+
+#define QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ_32BIT \
+ _IO(QSEECOM_IOC_MAGIC, 14)
+
+#define QSEECOM_IOCTL_APP_LOADED_QUERY_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 15, struct qseecom_qseos_app_load_query_32bit)
+
+#define QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 16, struct qseecom_send_svc_cmd_req_32bit)
+
+#define QSEECOM_IOCTL_CREATE_KEY_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 17, struct qseecom_create_key_req_32bit)
+
+#define QSEECOM_IOCTL_WIPE_KEY_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req_32bit)
+
+#define QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 19, \
+ struct qseecom_save_partition_hash_req_32bit)
+
+#define QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 20, struct qseecom_is_es_activated_req_32bit)
+
+#define QSEECOM_IOCTL_SEND_MODFD_RESP_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 21, \
+ struct qseecom_send_modfd_listener_resp_32bit)
+
+#define QSEECOM_IOCTL_SET_BUS_SCALING_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 23, int)
+
+#define QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 24, \
+ struct qseecom_update_key_userinfo_req_32bit)
+
+#define QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 30, struct qseecom_qteec_modfd_req_32bit)
+
+#define QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 31, struct qseecom_qteec_req_32bit)
+
+#define QSEECOM_QTEEC_IOCTL_INVOKE_MODFD_CMD_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 32, struct qseecom_qteec_modfd_req_32bit)
+
+#define QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 33, struct qseecom_qteec_modfd_req_32bit)
+
+#define QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 34, struct qseecom_mdtp_cipher_dip_req_32bit)
+
+#define QSEECOM_IOCTL_SEND_MODFD_CMD_64_REQ_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 35, struct qseecom_send_modfd_cmd_req_32bit)
+
+#define QSEECOM_IOCTL_SEND_MODFD_RESP_64_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 36, \
+ struct qseecom_send_modfd_listener_resp_32bit)
+#define QSEECOM_IOCTL_GET_CE_PIPE_INFO_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 40, \
+ struct qseecom_ce_info_req)
+#define QSEECOM_IOCTL_FREE_CE_PIPE_INFO_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 41, \
+ struct qseecom_ce_info_req)
+#define QSEECOM_IOCTL_QUERY_CE_PIPE_INFO_32BIT \
+ _IOWR(QSEECOM_IOC_MAGIC, 42, \
+ struct qseecom_ce_info_req_32bit)
+
+#endif
+#endif /* _UAPI_COMPAT_QSEECOM_H_ */
diff --git a/securemsm_kernel_vendor_board.mk b/securemsm_kernel_vendor_board.mk
index 5638d94..eade938 100644
--- a/securemsm_kernel_vendor_board.mk
+++ b/securemsm_kernel_vendor_board.mk
@@ -25,6 +25,9 @@ BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/tz_log_dlkm.ko \
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/tz_log_dlkm.ko \
$(KERNEL_MODULES_OUT)/hdcp_qseecom_dlkm.ko \
+ $(KERNEL_MODULES_OUT)/qrng_dlkm.ko \
+
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD += $(KERNEL_MODULES_OUT)/qrng_dlkm.ko
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD += $(KERNEL_MODULES_OUT)/hdcp_qseecom_dlkm.ko
@@ -37,5 +40,6 @@ ifneq (, $(filter true, $(TARGET_ENABLE_QSEECOM) $(TARGET_BOARD_AUTO)))
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/qseecom_dlkm.ko
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/qseecom_dlkm.ko
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD += $(KERNEL_MODULES_OUT)/qseecom_dlkm.ko
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD += $(KERNEL_MODULES_OUT)/qseecom_dlkm.ko
endif #TARGET_ENABLE_QSEECOM OR TARGET_BOARD_AUTO
endif #ENABLE_SECUREMSM_DLKM
diff --git a/smcinvoke/IClientEnv.h b/smcinvoke/IClientEnv.h
index 2c6d329..b974985 100644
--- a/smcinvoke/IClientEnv.h
+++ b/smcinvoke/IClientEnv.h
@@ -10,6 +10,8 @@
#define IClientEnv_OP_registerWithWhitelist 3
#define IClientEnv_OP_notifyDomainChange 4
#define IClientEnv_OP_registerWithCredentials 5
+#define IClientEnv_OP_accept 6
+#define IClientEnv_OP_adciShutdown 7
static inline int32_t
IClientEnv_release(struct Object self)
@@ -115,3 +117,14 @@ IClientEnv_registerWithCredentials(struct Object self, struct Object
return result;
}
+static inline int32_t
+IClientEnv_accept(struct Object self)
+{
+ return Object_invoke(self, IClientEnv_OP_accept, 0, 0);
+}
+
+static inline int32_t
+IClientEnv_adciShutdown(struct Object self)
+{
+ return Object_invoke(self, IClientEnv_OP_adciShutdown, 0, 0);
+}
diff --git a/smcinvoke/smcinvoke.c b/smcinvoke/smcinvoke.c
index 3932708..f230b8e 100644
--- a/smcinvoke/smcinvoke.c
+++ b/smcinvoke/smcinvoke.c
@@ -164,6 +164,7 @@ static DEFINE_MUTEX(g_smcinvoke_lock);
enum worker_thread_type {
SHMB_WORKER_THREAD = 0,
OBJECT_WORKER_THREAD,
+ ADCI_WORKER_THREAD,
MAX_THREAD_NUMBER
};
@@ -321,7 +322,8 @@ struct smcinvoke_worker_thread {
static struct smcinvoke_worker_thread smcinvoke[MAX_THREAD_NUMBER];
static const char thread_name[MAX_THREAD_NUMBER][MAX_CHAR_NAME] = {
- "smcinvoke_shmbridge_postprocess", "smcinvoke_object_postprocess"};
+ "smcinvoke_shmbridge_postprocess", "smcinvoke_object_postprocess", "smcinvoke_adci_thread"};
+static struct Object adci_clientEnv = Object_NULL;
static int prepare_send_scm_msg(const uint8_t *in_buf, phys_addr_t in_paddr,
size_t in_buf_len,
@@ -557,6 +559,38 @@ out:
return ret;
}
+static void smcinvoke_start_adci_thread(void)
+{
+
+ int32_t ret = OBJECT_ERROR;
+ int retry_count = 0;
+
+ ret = get_client_env_object(&adci_clientEnv);
+ if (ret) {
+ pr_err("failed to get clientEnv for ADCI invoke thread. ret = %d\n", ret);
+ adci_clientEnv = Object_NULL;
+ goto out;
+ }
+ /* Invoke call to QTEE which should never return if ADCI is supported */
+ do {
+ ret = IClientEnv_accept(adci_clientEnv);
+ if (ret == OBJECT_ERROR_BUSY) {
+ pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
+ msleep(5);
+ }
+ } while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));
+
+ if (ret == OBJECT_ERROR_INVALID)
+ pr_err("ADCI feature is not supported on this chipsets, ret = %d\n", ret);
+ /* Need to take decesion here if we want to restart the ADCI thread */
+ else
+ pr_err("Received response from QTEE, ret = %d\n", ret);
+out:
+ /* Control should reach to this point only if ADCI feature is not supported by QTEE
+ (or) ADCI thread held in QTEE is released. */
+ Object_ASSIGN_NULL(adci_clientEnv);
+}
+
static void __wakeup_postprocess_kthread(struct smcinvoke_worker_thread *smcinvoke)
{
if (smcinvoke) {
@@ -579,29 +613,45 @@ static int smcinvoke_postprocess_kthread_func(void *data)
return -EINVAL;
}
- tag = smcinvoke_wrk_trd->type == SHMB_WORKER_THREAD ? "shmbridge":"object";
-
while (!kthread_should_stop()) {
wait_event_interruptible(
smcinvoke_wrk_trd->postprocess_kthread_wq,
kthread_should_stop() ||
(atomic_read(&smcinvoke_wrk_trd->postprocess_kthread_state)
== POST_KT_WAKEUP));
- pr_debug("kthread to %s postprocess is called %d\n",
- tag,
- atomic_read(&smcinvoke_wrk_trd->postprocess_kthread_state));
switch (smcinvoke_wrk_trd->type) {
case SHMB_WORKER_THREAD:
+ tag = "shmbridge";
+ pr_debug("kthread to %s postprocess is called %d\n",
+ tag, atomic_read(&smcinvoke_wrk_trd->postprocess_kthread_state));
smcinvoke_shmbridge_post_process();
break;
case OBJECT_WORKER_THREAD:
+ tag = "object";
+ pr_debug("kthread to %s postprocess is called %d\n",
+ tag, atomic_read(&smcinvoke_wrk_trd->postprocess_kthread_state));
smcinvoke_object_post_process();
break;
+ case ADCI_WORKER_THREAD:
+ tag = "adci";
+ pr_debug("kthread to %s postprocess is called %d\n",
+ tag, atomic_read(&smcinvoke_wrk_trd->postprocess_kthread_state));
+ smcinvoke_start_adci_thread();
+ break;
default:
pr_err("Invalid thread type(%d), do nothing.\n",
(int)smcinvoke_wrk_trd->type);
break;
}
+ /* For ADCI thread, if control reaches here, that indicates either ADCI
+ * thread is not supported (or) released by QTEE. Since ADCI thread is
+ * getting signaled only during the smcinvoke driver initialization,
+ * there is no point of putting the thread into sleep state again. All the
+ * required post-processing will be taken care by object and shmbridge threads.
+ */
+ if(smcinvoke_wrk_trd->type == ADCI_WORKER_THREAD) {
+ break;
+ }
atomic_set(&smcinvoke_wrk_trd->postprocess_kthread_state,
POST_KT_SLEEP);
}
@@ -615,7 +665,7 @@ static int smcinvoke_create_kthreads(void)
{
int i, rc = 0;
const enum worker_thread_type thread_type[MAX_THREAD_NUMBER] = {
- SHMB_WORKER_THREAD, OBJECT_WORKER_THREAD};
+ SHMB_WORKER_THREAD, OBJECT_WORKER_THREAD, ADCI_WORKER_THREAD};
for (i = 0; i < MAX_THREAD_NUMBER; i++) {
init_waitqueue_head(&smcinvoke[i].postprocess_kthread_wq);
@@ -639,9 +689,26 @@ static int smcinvoke_create_kthreads(void)
static void smcinvoke_destroy_kthreads(void)
{
int i;
+ int32_t ret = OBJECT_ERROR;
+ int retry_count = 0;
+
+ if(!Object_isNull(adci_clientEnv)) {
+ do {
+ ret = IClientEnv_adciShutdown(adci_clientEnv);
+ if (ret == OBJECT_ERROR_BUSY) {
+ pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
+ msleep(5);
+ }
+ } while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));
+ if(OBJECT_isERROR(ret)) {
+ pr_err("adciShutdown in QTEE failed with error = %d\n", ret);
+ }
+ Object_ASSIGN_NULL(adci_clientEnv);
+ }
- for (i = 0; i < MAX_THREAD_NUMBER; i++)
+ for (i = 0; i < MAX_THREAD_NUMBER; i++) {
kthread_stop(smcinvoke[i].postprocess_kthread_task);
+ }
}
static inline void free_mem_obj_locked(struct smcinvoke_mem_obj *mem_obj)
@@ -1348,7 +1415,7 @@ static int invoke_cmd_handler(int cmd, phys_addr_t in_paddr, size_t in_buf_len,
case SMCINVOKE_CB_RSP_CMD:
if (legacy_smc_call)
- qtee_shmbridge_inv_shm_buf(out_shm);
+ qtee_shmbridge_flush_shm_buf(out_shm);
ret = qcom_scm_invoke_callback_response(virt_to_phys(out_buf), out_buf_len,
result, response_type, data);
if (legacy_smc_call) {
@@ -2282,7 +2349,9 @@ static long process_invoke_req(struct file *filp, unsigned int cmd,
if (context_type == SMCINVOKE_OBJ_TYPE_TZ_OBJ &&
tzobj->tzhandle == SMCINVOKE_TZ_ROOT_OBJ &&
(req.op == IClientEnv_OP_notifyDomainChange ||
- req.op == IClientEnv_OP_registerWithCredentials)) {
+ req.op == IClientEnv_OP_registerWithCredentials ||
+ req.op == IClientEnv_OP_accept ||
+ req.op == IClientEnv_OP_adciShutdown)) {
pr_err("invalid rootenv op\n");
return -EINVAL;
}
@@ -2747,6 +2816,7 @@ static int smcinvoke_probe(struct platform_device *pdev)
pr_err("failed to get qseecom kernel func ops %d", rc);
}
#endif
+ __wakeup_postprocess_kthread(&smcinvoke[ADCI_WORKER_THREAD]);
return 0;
exit_destroy_device:
diff --git a/smcinvoke/smcinvoke_kernel.c b/smcinvoke/smcinvoke_kernel.c
index 200d327..320da7c 100644
--- a/smcinvoke/smcinvoke_kernel.c
+++ b/smcinvoke/smcinvoke_kernel.c
@@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/fdtable.h>
#include <linux/anon_inodes.h>
+#include <linux/delay.h>
#include <linux/kref.h>
#include <linux/types.h>
#include <linux/slab.h>
@@ -295,6 +296,7 @@ static int get_root_obj(struct Object *rootObj)
int32_t get_client_env_object(struct Object *clientEnvObj)
{
int32_t ret = OBJECT_ERROR;
+ int retry_count = 0;
struct Object rootObj = Object_NULL;
/* get rootObj */
@@ -305,8 +307,15 @@ int32_t get_client_env_object(struct Object *clientEnvObj)
}
/* get client env */
- ret = IClientEnv_registerWithCredentials(rootObj,
+ do {
+ ret = IClientEnv_registerWithCredentials(rootObj,
Object_NULL, clientEnvObj);
+ if (ret == OBJECT_ERROR_BUSY) {
+ pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
+ msleep(5);
+ }
+ } while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));
+
if (ret)
pr_err("Failed to get ClientEnvObject, ret = %d\n", ret);
Object_release(rootObj);
diff --git a/smcinvoke/smcinvoke_object.h b/smcinvoke/smcinvoke_object.h
index 27c66da..f3c2aa5 100644
--- a/smcinvoke/smcinvoke_object.h
+++ b/smcinvoke/smcinvoke_object.h
@@ -184,6 +184,7 @@ static inline void Object_replace(struct Object *loc, struct Object objNew)
}
#define Object_ASSIGN_NULL(loc) Object_replace(&(loc), Object_NULL)
+#define SMCINVOKE_INTERFACE_MAX_RETRY 5
int smcinvoke_release_from_kernel_client(int fd);