Skip to content

Commit c3fa24a

Browse files
b49020jenswi-linaro
authored andcommitted
tee: optee: add TEE bus device enumeration support
OP-TEE provides a pseudo TA to enumerate TAs which can act as devices/ services for TEE bus. So implement device enumeration using invoke function: PTA_CMD_GET_DEVICES provided by pseudo TA to fetch array of device UUIDs. Also register these enumerated devices with TEE bus as "optee-clntX" device. Signed-off-by: Sumit Garg <sumit.garg@linaro.org> Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org> [jw: fix optee_enumerate_devices() with no devices found] Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
1 parent 0fc1db9 commit c3fa24a

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

drivers/tee/optee/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ optee-objs += call.o
55
optee-objs += rpc.o
66
optee-objs += supp.o
77
optee-objs += shm_pool.o
8+
optee-objs += device.o

drivers/tee/optee/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,10 @@ static struct optee *optee_probe(struct device_node *np)
634634
if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
635635
pr_info("dynamic shared memory is enabled\n");
636636

637+
rc = optee_enumerate_devices();
638+
if (rc)
639+
goto err;
640+
637641
pr_info("initialized driver\n");
638642
return optee;
639643
err:

drivers/tee/optee/device.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2019 Linaro Ltd.
4+
*/
5+
6+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7+
8+
#include <linux/kernel.h>
9+
#include <linux/slab.h>
10+
#include <linux/tee_drv.h>
11+
#include <linux/uuid.h>
12+
#include "optee_private.h"
13+
14+
/*
15+
* Get device UUIDs
16+
*
17+
* [out] memref[0] Array of device UUIDs
18+
*
19+
* Return codes:
20+
* TEE_SUCCESS - Invoke command success
21+
* TEE_ERROR_BAD_PARAMETERS - Incorrect input param
22+
* TEE_ERROR_SHORT_BUFFER - Output buffer size less than required
23+
*/
24+
#define PTA_CMD_GET_DEVICES 0x0
25+
26+
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
27+
{
28+
if (ver->impl_id == TEE_IMPL_ID_OPTEE)
29+
return 1;
30+
else
31+
return 0;
32+
}
33+
34+
static int get_devices(struct tee_context *ctx, u32 session,
35+
struct tee_shm *device_shm, u32 *shm_size)
36+
{
37+
u32 ret = 0;
38+
struct tee_ioctl_invoke_arg inv_arg = {0};
39+
struct tee_param param[4] = {0};
40+
41+
/* Invoke PTA_CMD_GET_DEVICES function */
42+
inv_arg.func = PTA_CMD_GET_DEVICES;
43+
inv_arg.session = session;
44+
inv_arg.num_params = 4;
45+
46+
/* Fill invoke cmd params */
47+
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
48+
param[0].u.memref.shm = device_shm;
49+
param[0].u.memref.size = *shm_size;
50+
param[0].u.memref.shm_offs = 0;
51+
52+
ret = tee_client_invoke_func(ctx, &inv_arg, param);
53+
if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
54+
(inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
55+
pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
56+
inv_arg.ret);
57+
return -EINVAL;
58+
}
59+
60+
*shm_size = param[0].u.memref.size;
61+
62+
return 0;
63+
}
64+
65+
static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
66+
{
67+
struct tee_client_device *optee_device = NULL;
68+
int rc;
69+
70+
optee_device = kzalloc(sizeof(*optee_device), GFP_KERNEL);
71+
if (!optee_device)
72+
return -ENOMEM;
73+
74+
optee_device->dev.bus = &tee_bus_type;
75+
dev_set_name(&optee_device->dev, "optee-clnt%u", device_id);
76+
uuid_copy(&optee_device->id.uuid, device_uuid);
77+
78+
rc = device_register(&optee_device->dev);
79+
if (rc) {
80+
pr_err("device registration failed, err: %d\n", rc);
81+
kfree(optee_device);
82+
}
83+
84+
return rc;
85+
}
86+
87+
int optee_enumerate_devices(void)
88+
{
89+
const uuid_t pta_uuid =
90+
UUID_INIT(0x7011a688, 0xddde, 0x4053,
91+
0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
92+
struct tee_ioctl_open_session_arg sess_arg = {0};
93+
struct tee_shm *device_shm = NULL;
94+
const uuid_t *device_uuid = NULL;
95+
struct tee_context *ctx = NULL;
96+
u32 shm_size = 0, idx, num_devices = 0;
97+
int rc;
98+
99+
/* Open context with OP-TEE driver */
100+
ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
101+
if (IS_ERR(ctx))
102+
return -ENODEV;
103+
104+
/* Open session with device enumeration pseudo TA */
105+
memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN);
106+
sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
107+
sess_arg.num_params = 0;
108+
109+
rc = tee_client_open_session(ctx, &sess_arg, NULL);
110+
if ((rc < 0) || (sess_arg.ret != TEEC_SUCCESS)) {
111+
/* Device enumeration pseudo TA not found */
112+
rc = 0;
113+
goto out_ctx;
114+
}
115+
116+
rc = get_devices(ctx, sess_arg.session, NULL, &shm_size);
117+
if (rc < 0 || !shm_size)
118+
goto out_sess;
119+
120+
device_shm = tee_shm_alloc(ctx, shm_size,
121+
TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
122+
if (IS_ERR(device_shm)) {
123+
pr_err("tee_shm_alloc failed\n");
124+
rc = PTR_ERR(device_shm);
125+
goto out_sess;
126+
}
127+
128+
rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size);
129+
if (rc < 0)
130+
goto out_shm;
131+
132+
device_uuid = tee_shm_get_va(device_shm, 0);
133+
if (IS_ERR(device_uuid)) {
134+
pr_err("tee_shm_get_va failed\n");
135+
rc = PTR_ERR(device_uuid);
136+
goto out_shm;
137+
}
138+
139+
num_devices = shm_size / sizeof(uuid_t);
140+
141+
for (idx = 0; idx < num_devices; idx++) {
142+
rc = optee_register_device(&device_uuid[idx], idx);
143+
if (rc)
144+
goto out_shm;
145+
}
146+
147+
out_shm:
148+
tee_shm_free(device_shm);
149+
out_sess:
150+
tee_client_close_session(ctx, sess_arg.session);
151+
out_ctx:
152+
tee_client_close_context(ctx);
153+
154+
return rc;
155+
}

drivers/tee/optee/optee_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
2929
#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
3030
#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
31+
#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
3132

3233
#define TEEC_ORIGIN_COMMS 0x00000002
3334

@@ -181,6 +182,8 @@ void optee_free_pages_list(void *array, size_t num_entries);
181182
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
182183
size_t page_offset);
183184

185+
int optee_enumerate_devices(void);
186+
184187
/*
185188
* Small helpers
186189
*/

0 commit comments

Comments
 (0)