projects/linux·blob master · refs

195 lines · 4.6 KiB

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_core.h>
11#include <linux/uuid.h>
12#include "optee_private.h"
13
14static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
15{
16 return (ver->impl_id == TEE_IMPL_ID_OPTEE);
17}
18
19static int get_devices(struct tee_context *ctx, u32 session,
20 struct tee_shm *device_shm, u32 *shm_size,
21 u32 func)
22{
23 int ret = 0;
24 struct tee_ioctl_invoke_arg inv_arg;
25 struct tee_param param[4];
26
27 memset(&inv_arg, 0, sizeof(inv_arg));
28 memset(&param, 0, sizeof(param));
29
30 inv_arg.func = func;
31 inv_arg.session = session;
32 inv_arg.num_params = 4;
33
34 /* Fill invoke cmd params */
35 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
36 param[0].u.memref.shm = device_shm;
37 param[0].u.memref.size = *shm_size;
38 param[0].u.memref.shm_offs = 0;
39
40 ret = tee_client_invoke_func(ctx, &inv_arg, param);
41 if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
42 (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
43 /*
44 * TEE_ERROR_STORAGE_NOT_AVAILABLE is returned when getting
45 * the list of device TAs that depends on RPMB but a usable
46 * RPMB device isn't found.
47 */
48 if (inv_arg.ret == TEE_ERROR_STORAGE_NOT_AVAILABLE)
49 return -ENODEV;
50 pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
51 inv_arg.ret);
52 return -EINVAL;
53 }
54
55 *shm_size = param[0].u.memref.size;
56
57 return 0;
58}
59
60static void optee_release_device(struct device *dev)
61{
62 struct tee_client_device *optee_device = to_tee_client_device(dev);
63
64 kfree(optee_device);
65}
66
67static ssize_t need_supplicant_show(struct device *dev,
68 struct device_attribute *attr,
69 char *buf)
70{
71 return 0;
72}
73
74static DEVICE_ATTR_RO(need_supplicant);
75
76static int optee_register_device(const uuid_t *device_uuid, u32 func)
77{
78 struct tee_client_device *optee_device = NULL;
79 int rc;
80
81 optee_device = kzalloc_obj(*optee_device);
82 if (!optee_device)
83 return -ENOMEM;
84
85 optee_device->dev.bus = &tee_bus_type;
86 optee_device->dev.release = optee_release_device;
87 if (dev_set_name(&optee_device->dev, "optee-ta-%pUb", device_uuid)) {
88 kfree(optee_device);
89 return -ENOMEM;
90 }
91 uuid_copy(&optee_device->id.uuid, device_uuid);
92
93 rc = device_register(&optee_device->dev);
94 if (rc) {
95 pr_err("device registration failed, err: %d\n", rc);
96 put_device(&optee_device->dev);
97 return rc;
98 }
99
100 if (func == PTA_CMD_GET_DEVICES_SUPP)
101 device_create_file(&optee_device->dev,
102 &dev_attr_need_supplicant);
103
104 return 0;
105}
106
107static int __optee_enumerate_devices(u32 func)
108{
109 const uuid_t pta_uuid =
110 UUID_INIT(0x7011a688, 0xddde, 0x4053,
111 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
112 struct tee_ioctl_open_session_arg sess_arg;
113 struct tee_shm *device_shm = NULL;
114 const uuid_t *device_uuid = NULL;
115 struct tee_context *ctx = NULL;
116 u32 shm_size = 0, idx, num_devices = 0;
117 int rc;
118
119 memset(&sess_arg, 0, sizeof(sess_arg));
120
121 /* Open context with OP-TEE driver */
122 ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
123 if (IS_ERR(ctx))
124 return -ENODEV;
125
126 /* Open session with device enumeration pseudo TA */
127 export_uuid(sess_arg.uuid, &pta_uuid);
128 sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
129 sess_arg.num_params = 0;
130
131 rc = tee_client_open_session(ctx, &sess_arg, NULL);
132 if ((rc < 0) || (sess_arg.ret != TEEC_SUCCESS)) {
133 /* Device enumeration pseudo TA not found */
134 rc = 0;
135 goto out_ctx;
136 }
137
138 rc = get_devices(ctx, sess_arg.session, NULL, &shm_size, func);
139 if (rc < 0 || !shm_size)
140 goto out_sess;
141
142 device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
143 if (IS_ERR(device_shm)) {
144 pr_err("tee_shm_alloc_kernel_buf failed\n");
145 rc = PTR_ERR(device_shm);
146 goto out_sess;
147 }
148
149 rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size, func);
150 if (rc < 0)
151 goto out_shm;
152
153 device_uuid = tee_shm_get_va(device_shm, 0);
154 if (IS_ERR(device_uuid)) {
155 pr_err("tee_shm_get_va failed\n");
156 rc = PTR_ERR(device_uuid);
157 goto out_shm;
158 }
159
160 num_devices = shm_size / sizeof(uuid_t);
161
162 for (idx = 0; idx < num_devices; idx++) {
163 rc = optee_register_device(&device_uuid[idx], func);
164 if (rc)
165 goto out_shm;
166 }
167
168out_shm:
169 tee_shm_free(device_shm);
170out_sess:
171 tee_client_close_session(ctx, sess_arg.session);
172out_ctx:
173 tee_client_close_context(ctx);
174
175 return rc;
176}
177
178int optee_enumerate_devices(u32 func)
179{
180 return __optee_enumerate_devices(func);
181}
182
183static int __optee_unregister_device(struct device *dev, void *data)
184{
185 if (!strncmp(dev_name(dev), "optee-ta", strlen("optee-ta")))
186 device_unregister(dev);
187
188 return 0;
189}
190
191void optee_unregister_devices(void)
192{
193 bus_for_each_dev(&tee_bus_type, NULL, NULL,
194 __optee_unregister_device);
195}