xref: /linux/drivers/nvmem/stm32-bsec-optee-ta.c (revision 8e07e0e3964ca4e23ce7b68e2096fe660a888942)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
4  *
5  * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
6  */
7 
8 #include <linux/tee_drv.h>
9 
10 #include "stm32-bsec-optee-ta.h"
11 
12 /*
13  * Read OTP memory
14  *
15  * [in]		value[0].a		OTP start offset in byte
16  * [in]		value[0].b		Access type (0:shadow, 1:fuse, 2:lock)
17  * [out]	memref[1].buffer	Output buffer to store read values
18  * [out]	memref[1].size		Size of OTP to be read
19  *
20  * Return codes:
21  * TEE_SUCCESS - Invoke command success
22  * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
23  * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
24  */
25 #define PTA_BSEC_READ_MEM		0x0
26 
27 /*
28  * Write OTP memory
29  *
30  * [in]		value[0].a		OTP start offset in byte
31  * [in]		value[0].b		Access type (0:shadow, 1:fuse, 2:lock)
32  * [in]		memref[1].buffer	Input buffer to read values
33  * [in]		memref[1].size		Size of OTP to be written
34  *
35  * Return codes:
36  * TEE_SUCCESS - Invoke command success
37  * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
38  * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
39  */
40 #define PTA_BSEC_WRITE_MEM		0x1
41 
42 /* value of PTA_BSEC access type = value[in] b */
43 #define SHADOW_ACCESS	0
44 #define FUSE_ACCESS	1
45 #define LOCK_ACCESS	2
46 
47 /* Bitfield definition for LOCK status */
48 #define LOCK_PERM			BIT(30)
49 
50 /* OP-TEE STM32MP BSEC TA UUID */
51 static const uuid_t stm32mp_bsec_ta_uuid =
52 	UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5,
53 		  0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03);
54 
55 /*
56  * Check whether this driver supports the BSEC TA in the TEE instance
57  * represented by the params (ver/data) to this function.
58  */
59 static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver,
60 				     const void *data)
61 {
62 	/* Currently this driver only supports GP compliant, OP-TEE based TA */
63 	if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
64 		(ver->gen_caps & TEE_GEN_CAP_GP))
65 		return 1;
66 	else
67 		return 0;
68 }
69 
70 /* Open a session to OP-TEE for STM32MP BSEC TA */
71 static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id)
72 {
73 	struct tee_ioctl_open_session_arg sess_arg;
74 	int rc;
75 
76 	memset(&sess_arg, 0, sizeof(sess_arg));
77 	export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid);
78 	sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
79 	sess_arg.num_params = 0;
80 
81 	rc = tee_client_open_session(ctx, &sess_arg, NULL);
82 	if ((rc < 0) || (sess_arg.ret != 0)) {
83 		pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
84 		       __func__, sess_arg.ret, rc);
85 		if (!rc)
86 			rc = -EINVAL;
87 	} else {
88 		*id = sess_arg.session;
89 	}
90 
91 	return rc;
92 }
93 
94 /* close a session to OP-TEE for STM32MP BSEC TA */
95 static void stm32_bsec_ta_close_session(void *ctx, u32 id)
96 {
97 	tee_client_close_session(ctx, id);
98 }
99 
100 /* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */
101 int stm32_bsec_optee_ta_open(struct tee_context **ctx)
102 {
103 	struct tee_context *tee_ctx;
104 	u32 session_id;
105 	int rc;
106 
107 	/* Open context with TEE driver */
108 	tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL);
109 	if (IS_ERR(tee_ctx)) {
110 		rc = PTR_ERR(tee_ctx);
111 		if (rc == -ENOENT)
112 			return -EPROBE_DEFER;
113 		pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc);
114 
115 		return rc;
116 	}
117 
118 	/* Check STM32MP BSEC TA presence */
119 	rc = stm32_bsec_ta_open_session(tee_ctx, &session_id);
120 	if (rc) {
121 		tee_client_close_context(tee_ctx);
122 		return rc;
123 	}
124 
125 	stm32_bsec_ta_close_session(tee_ctx, session_id);
126 
127 	*ctx = tee_ctx;
128 
129 	return 0;
130 }
131 
132 /* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */
133 void stm32_bsec_optee_ta_close(void *ctx)
134 {
135 	tee_client_close_context(ctx);
136 }
137 
138 /* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */
139 int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
140 			     void *buf, size_t bytes)
141 {
142 	struct tee_shm *shm;
143 	struct tee_ioctl_invoke_arg arg;
144 	struct tee_param param[2];
145 	u8 *shm_buf;
146 	u32 start, num_bytes;
147 	int ret;
148 	u32 session_id;
149 
150 	ret = stm32_bsec_ta_open_session(ctx, &session_id);
151 	if (ret)
152 		return ret;
153 
154 	memset(&arg, 0, sizeof(arg));
155 	memset(&param, 0, sizeof(param));
156 
157 	arg.func = PTA_BSEC_READ_MEM;
158 	arg.session = session_id;
159 	arg.num_params = 2;
160 
161 	/* align access on 32bits */
162 	start = ALIGN_DOWN(offset, 4);
163 	num_bytes = round_up(offset + bytes - start, 4);
164 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
165 	param[0].u.value.a = start;
166 	param[0].u.value.b = SHADOW_ACCESS;
167 
168 	shm = tee_shm_alloc_kernel_buf(ctx, num_bytes);
169 	if (IS_ERR(shm)) {
170 		ret = PTR_ERR(shm);
171 		goto out_tee_session;
172 	}
173 
174 	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
175 	param[1].u.memref.shm = shm;
176 	param[1].u.memref.size = num_bytes;
177 
178 	ret = tee_client_invoke_func(ctx, &arg, param);
179 	if (ret < 0 || arg.ret != 0) {
180 		pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n",
181 			arg.ret, ret);
182 		if (!ret)
183 			ret = -EIO;
184 	}
185 	if (!ret) {
186 		shm_buf = tee_shm_get_va(shm, 0);
187 		if (IS_ERR(shm_buf)) {
188 			ret = PTR_ERR(shm_buf);
189 			pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
190 		} else {
191 			/* read data from 32 bits aligned buffer */
192 			memcpy(buf, &shm_buf[offset % 4], bytes);
193 		}
194 	}
195 
196 	tee_shm_free(shm);
197 
198 out_tee_session:
199 	stm32_bsec_ta_close_session(ctx, session_id);
200 
201 	return ret;
202 }
203 
204 /* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */
205 int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
206 			      unsigned int offset, void *buf, size_t bytes)
207 {	struct tee_shm *shm;
208 	struct tee_ioctl_invoke_arg arg;
209 	struct tee_param param[2];
210 	u8 *shm_buf;
211 	int ret;
212 	u32 session_id;
213 
214 	ret = stm32_bsec_ta_open_session(ctx, &session_id);
215 	if (ret)
216 		return ret;
217 
218 	/* Allow only writing complete 32-bits aligned words */
219 	if ((bytes % 4) || (offset % 4))
220 		return -EINVAL;
221 
222 	memset(&arg, 0, sizeof(arg));
223 	memset(&param, 0, sizeof(param));
224 
225 	arg.func = PTA_BSEC_WRITE_MEM;
226 	arg.session = session_id;
227 	arg.num_params = 2;
228 
229 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
230 	param[0].u.value.a = offset;
231 	param[0].u.value.b = FUSE_ACCESS;
232 
233 	shm = tee_shm_alloc_kernel_buf(ctx, bytes);
234 	if (IS_ERR(shm)) {
235 		ret = PTR_ERR(shm);
236 		goto out_tee_session;
237 	}
238 
239 	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
240 	param[1].u.memref.shm = shm;
241 	param[1].u.memref.size = bytes;
242 
243 	shm_buf = tee_shm_get_va(shm, 0);
244 	if (IS_ERR(shm_buf)) {
245 		ret = PTR_ERR(shm_buf);
246 		pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
247 		tee_shm_free(shm);
248 
249 		goto out_tee_session;
250 	}
251 
252 	memcpy(shm_buf, buf, bytes);
253 
254 	ret = tee_client_invoke_func(ctx, &arg, param);
255 	if (ret < 0 || arg.ret != 0) {
256 		pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
257 		if (!ret)
258 			ret = -EIO;
259 	}
260 	pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret);
261 
262 	/* Lock the upper OTPs with ECC protection, word programming only */
263 	if (!ret && ((offset + bytes) >= (lower * 4))) {
264 		u32 start, nb_lock;
265 		u32 *lock = (u32 *)shm_buf;
266 		int i;
267 
268 		/*
269 		 * don't lock the lower OTPs, no ECC protection and incremental
270 		 * bit programming, a second write is allowed
271 		 */
272 		start = max_t(u32, offset, lower * 4);
273 		nb_lock = (offset + bytes - start) / 4;
274 
275 		param[0].u.value.a = start;
276 		param[0].u.value.b = LOCK_ACCESS;
277 		param[1].u.memref.size = nb_lock * 4;
278 
279 		for (i = 0; i < nb_lock; i++)
280 			lock[i] = LOCK_PERM;
281 
282 		ret = tee_client_invoke_func(ctx, &arg, param);
283 		if (ret < 0 || arg.ret != 0) {
284 			pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
285 			if (!ret)
286 				ret = -EIO;
287 		}
288 		pr_debug("Lock upper OTPs %d to %d, ret=%d\n",
289 			 start / 4, start / 4 + nb_lock, ret);
290 	}
291 
292 	tee_shm_free(shm);
293 
294 out_tee_session:
295 	stm32_bsec_ta_close_session(ctx, session_id);
296 
297 	return ret;
298 }
299