1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 Linaro Ltd.
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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"
17 * [out] memref[0] Array of device UUIDs
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
24 #define PTA_CMD_GET_DEVICES 0x0
26 static int optee_ctx_match(struct tee_ioctl_version_data
*ver
, const void *data
)
28 if (ver
->impl_id
== TEE_IMPL_ID_OPTEE
)
34 static int get_devices(struct tee_context
*ctx
, u32 session
,
35 struct tee_shm
*device_shm
, u32
*shm_size
)
38 struct tee_ioctl_invoke_arg inv_arg
;
39 struct tee_param param
[4];
41 memset(&inv_arg
, 0, sizeof(inv_arg
));
42 memset(¶m
, 0, sizeof(param
));
44 /* Invoke PTA_CMD_GET_DEVICES function */
45 inv_arg
.func
= PTA_CMD_GET_DEVICES
;
46 inv_arg
.session
= session
;
47 inv_arg
.num_params
= 4;
49 /* Fill invoke cmd params */
50 param
[0].attr
= TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT
;
51 param
[0].u
.memref
.shm
= device_shm
;
52 param
[0].u
.memref
.size
= *shm_size
;
53 param
[0].u
.memref
.shm_offs
= 0;
55 ret
= tee_client_invoke_func(ctx
, &inv_arg
, param
);
56 if ((ret
< 0) || ((inv_arg
.ret
!= TEEC_SUCCESS
) &&
57 (inv_arg
.ret
!= TEEC_ERROR_SHORT_BUFFER
))) {
58 pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
63 *shm_size
= param
[0].u
.memref
.size
;
68 static int optee_register_device(const uuid_t
*device_uuid
, u32 device_id
)
70 struct tee_client_device
*optee_device
= NULL
;
73 optee_device
= kzalloc(sizeof(*optee_device
), GFP_KERNEL
);
77 optee_device
->dev
.bus
= &tee_bus_type
;
78 dev_set_name(&optee_device
->dev
, "optee-clnt%u", device_id
);
79 uuid_copy(&optee_device
->id
.uuid
, device_uuid
);
81 rc
= device_register(&optee_device
->dev
);
83 pr_err("device registration failed, err: %d\n", rc
);
90 int optee_enumerate_devices(void)
92 const uuid_t pta_uuid
=
93 UUID_INIT(0x7011a688, 0xddde, 0x4053,
94 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
95 struct tee_ioctl_open_session_arg sess_arg
;
96 struct tee_shm
*device_shm
= NULL
;
97 const uuid_t
*device_uuid
= NULL
;
98 struct tee_context
*ctx
= NULL
;
99 u32 shm_size
= 0, idx
, num_devices
= 0;
102 memset(&sess_arg
, 0, sizeof(sess_arg
));
104 /* Open context with OP-TEE driver */
105 ctx
= tee_client_open_context(NULL
, optee_ctx_match
, NULL
, NULL
);
109 /* Open session with device enumeration pseudo TA */
110 memcpy(sess_arg
.uuid
, pta_uuid
.b
, TEE_IOCTL_UUID_LEN
);
111 sess_arg
.clnt_login
= TEE_IOCTL_LOGIN_PUBLIC
;
112 sess_arg
.num_params
= 0;
114 rc
= tee_client_open_session(ctx
, &sess_arg
, NULL
);
115 if ((rc
< 0) || (sess_arg
.ret
!= TEEC_SUCCESS
)) {
116 /* Device enumeration pseudo TA not found */
121 rc
= get_devices(ctx
, sess_arg
.session
, NULL
, &shm_size
);
122 if (rc
< 0 || !shm_size
)
125 device_shm
= tee_shm_alloc(ctx
, shm_size
,
126 TEE_SHM_MAPPED
| TEE_SHM_DMA_BUF
);
127 if (IS_ERR(device_shm
)) {
128 pr_err("tee_shm_alloc failed\n");
129 rc
= PTR_ERR(device_shm
);
133 rc
= get_devices(ctx
, sess_arg
.session
, device_shm
, &shm_size
);
137 device_uuid
= tee_shm_get_va(device_shm
, 0);
138 if (IS_ERR(device_uuid
)) {
139 pr_err("tee_shm_get_va failed\n");
140 rc
= PTR_ERR(device_uuid
);
144 num_devices
= shm_size
/ sizeof(uuid_t
);
146 for (idx
= 0; idx
< num_devices
; idx
++) {
147 rc
= optee_register_device(&device_uuid
[idx
], idx
);
153 tee_shm_free(device_shm
);
155 tee_client_close_session(ctx
, sess_arg
.session
);
157 tee_client_close_context(ctx
);