1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2022 Foundries.io Ltd
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <initcall.h>
8 #include <kernel/delay.h>
9 #include <kernel/panic.h>
10 #include <mm/core_mmu.h>
11 #include <string.h>
12 #include <tee/cache.h>
13 #include "drivers/versal_mbox.h"
14 
15 #define PM_SIP_SVC	0xc2000000
16 
17 /* IPI targets */
18 #define IPI_ID_PMC	1
19 #define IPI_ID_0	2
20 #define IPI_ID_RPU0	3
21 #define IPI_ID_RPU1	4
22 #define IPI_ID_3	5
23 #define IPI_ID_4	6
24 #define IPI_ID_5	7
25 
26 /* Buffers */
27 #define IPI_BUFFER_BASEADDR		0xFF3F0000
28 #define IPI_BUFFER_APU_ID_0_BASE	(IPI_BUFFER_BASEADDR + 0x400)
29 #define IPI_BUFFER_APU_ID_3_BASE	(IPI_BUFFER_BASEADDR + 0xA00)
30 #define IPI_BUFFER_APU_ID_4_BASE	(IPI_BUFFER_BASEADDR + 0xC00)
31 #define IPI_BUFFER_APU_ID_5_BASE	(IPI_BUFFER_BASEADDR + 0xE00)
32 #define IPI_BUFFER_PMC_BASE		(IPI_BUFFER_BASEADDR + 0x200)
33 #define IPI_BUFFER_TARGET_APU_OFFSET	0x80
34 #define IPI_BUFFER_TARGET_PMC_OFFSET	0x40
35 #define IPI_BUFFER_REQ_OFFSET		0x0
36 #define IPI_BUFFER_RESP_OFFSET		0x20
37 
38 #define IPI_BUFFER_LOCAL_OFFSET		IPI_BUFFER_TARGET_APU_OFFSET
39 #define IPI_BUFFER_REMOTE_OFFSET	IPI_BUFFER_TARGET_PMC_OFFSET
40 
41 #define IPI_BLOCK		1
42 #define IPI_NON_BLOCK		0
43 
44 /* Mailbox api */
45 enum versal_ipi_api_id {
46 	IPI_MAILBOX_OPEN = 0x1000,
47 	IPI_MAILBOX_RELEASE,
48 	IPI_MAILBOX_STATUS_ENQUIRY,
49 	IPI_MAILBOX_NOTIFY,
50 	IPI_MAILBOX_ACK,
51 	IPI_MAILBOX_ENABLE_IRQ,
52 	IPI_MAILBOX_DISABLE_IRQ
53 };
54 
55 static struct versal_ipi {
56 	uint32_t lcl;
57 	const uint32_t rmt;
58 	paddr_t buf;
59 	/* Exclusive access to the IPI shared buffer */
60 	struct mutex lock;
61 	void *rsp;
62 	void *req;
63 } ipi = {
64 	.buf = IPI_BUFFER_APU_ID_3_BASE,
65 	.rmt = IPI_ID_PMC,
66 	.lcl = IPI_ID_3,
67 };
68 
69 static const char *const nvm_id[] = {
70 	[0] = "API_FEATURES",
71 	[1] = "BBRAM_WRITE_AES_KEY",
72 	[2] = "BBRAM_ZEROIZE",
73 	[3] = "BBRAM_WRITE_USER_DATA",
74 	[4] = "BBRAM_READ_USER_DATA",
75 	[5] = "BBRAM_LOCK_WRITE_USER_DATA",
76 	[6] = "EFUSE_WRITE",
77 	[7] = "EFUSE_WRITE_PUF",
78 	[8] = "EFUSE_PUF_USER_FUSE_WRITE",
79 	[9] = "EFUSE_READ_IV",
80 	[10] = "EFUSE_READ_REVOCATION_ID",
81 	[11] = "EFUSE_READ_OFFCHIP_REVOCATION_ID",
82 	[12] = "EFUSE_READ_USER_FUSES",
83 	[13] = "EFUSE_READ_MISC_CTRL",
84 	[14] = "EFUSE_READ_SEC_CTRL",
85 	[15] = "EFUSE_READ_SEC_MISC1",
86 	[16] = "EFUSE_READ_BOOT_ENV_CTRL",
87 	[17] = "EFUSE_READ_PUF_SEC_CTRL",
88 	[18] = "EFUSE_READ_PPK_HASH",
89 	[19] = "EFUSE_READ_DEC_EFUSE_ONLY",
90 	[20] = "EFUSE_READ_DNA",
91 	[21] = "EFUSE_READ_PUF_USER_FUSES",
92 	[22] = "EFUSE_READ_PUF",
93 	[23] = "EFUSE_INVALID",
94 };
95 
96 static const char *const crypto_id[] = {
97 	[0] = "FEATURES",
98 	[1] = "RSA_SIGN_VERIFY",
99 	[2] = "RSA_PUBLIC_ENCRYPT",
100 	[3] = "RSA_PRIVATE_DECRYPT",
101 	[4] = "RSA_KAT",
102 	[32] = "SHA3_UPDATE",
103 	[33] = "SHA3_KAT",
104 	[64] = "ELLIPTIC_GENERATE_PUBLIC_KEY",
105 	[65] = "ELLIPTIC_GENERATE_SIGN",
106 	[66] = "ELLIPTIC_VALIDATE_PUBLIC_KEY",
107 	[67] = "ELLIPTIC_VERIFY_SIGN",
108 	[68] = "ELLIPTIC_KAT",
109 	[96] = "AES_INIT",
110 	[97] = "AES_OP_INIT",
111 	[98] = "AES_UPDATE_AAD",
112 	[99] = "AES_ENCRYPT_UPDATE",
113 	[100] = "AES_ENCRYPT_FINAL",
114 	[101] = "AES_DECRYPT_UPDATE",
115 	[102] = "AES_DECRYPT_FINAL",
116 	[103] = "AES_KEY_ZERO",
117 	[104] = "AES_WRITE_KEY",
118 	[105] = "AES_LOCK_USER_KEY",
119 	[106] = "AES_KEK_DECRYPT",
120 	[107] = "AES_SET_DPA_CM",
121 	[108] = "AES_DECRYPT_KAT",
122 	[109] = "AES_DECRYPT_CM_KAT",
123 	[110] = "MAX",
124 };
125 
126 static const char *const puf_id[] = {
127 	[0] = "PUF_API_FEATURES",
128 	[1] = "PUF_REGISTRATION",
129 	[2] = "PUF_REGENERATION",
130 	[3] = "PUF_CLEAR_PUF_ID",
131 };
132 
133 static const char *const module[] = {
134 	[5] = "CRYPTO",
135 	[7] = "FPGA",
136 	[11] = "NVM",
137 	[12] = "PUF",
138 };
139 
140 static const char *const fpga_id[] = {
141 	[1] = "LOAD",
142 };
143 
versal_mbox_call_trace(uint32_t call)144 static void versal_mbox_call_trace(uint32_t call)
145 {
146 	uint32_t mid = call >>  8 & 0xff;
147 	uint32_t api = call & 0xff;
148 	const char *val = NULL;
149 
150 	switch (mid) {
151 	case 5:
152 		if (api < ARRAY_SIZE(crypto_id))
153 			val = crypto_id[api];
154 
155 		break;
156 	case 7:
157 		if (api < ARRAY_SIZE(fpga_id))
158 			val = fpga_id[api];
159 
160 		break;
161 	case 11:
162 		if (api < ARRAY_SIZE(nvm_id))
163 			val = nvm_id[api];
164 
165 		break;
166 	case 12:
167 		if (api < ARRAY_SIZE(puf_id))
168 			val = puf_id[api];
169 
170 		break;
171 	default:
172 		break;
173 	}
174 
175 	IMSG("--- mbox: service: %s\t call: %s", module[mid],
176 	     val ? val : "Invalid");
177 };
178 
mbox_call(enum versal_ipi_api_id id,uint32_t blocking_call)179 static TEE_Result mbox_call(enum versal_ipi_api_id id, uint32_t blocking_call)
180 {
181 	struct thread_smc_args args = {
182 		.a0 = PM_SIP_SVC | id,
183 		.a1 = reg_pair_to_64(0, ipi.lcl),
184 		.a2 = reg_pair_to_64(0, ipi.rmt),
185 		.a3 = reg_pair_to_64(0, blocking_call),
186 	};
187 
188 	thread_smccc(&args);
189 
190 	/* Give the PLM time to access the console */
191 	if (IS_ENABLED(CFG_VERSAL_TRACE_PLM))
192 		mdelay(500);
193 
194 	if (args.a0)
195 		return TEE_ERROR_GENERIC;
196 
197 	return TEE_SUCCESS;
198 }
199 
versal_mbox_write_req(struct versal_ipi_cmd * cmd)200 static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd)
201 {
202 	size_t i = 0;
203 
204 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
205 		if (!cmd->ibuf[i].mem.buf)
206 			continue;
207 
208 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
209 				CACHELINE_LEN)) {
210 			EMSG("address not aligned: buffer %zu - %p", i,
211 			     cmd->ibuf[i].mem.buf);
212 			return TEE_ERROR_GENERIC;
213 		}
214 
215 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
216 			EMSG("length not aligned: buffer %zu - %zu",
217 			     i, cmd->ibuf[i].mem.alloc_len);
218 			return TEE_ERROR_GENERIC;
219 		}
220 
221 		cache_operation(TEE_CACHEFLUSH, cmd->ibuf[i].mem.buf,
222 				cmd->ibuf[i].mem.alloc_len);
223 	}
224 
225 	memcpy(ipi.req, cmd->data, sizeof(cmd->data));
226 
227 	/* Cache operation on the IPI buffer is safe */
228 	cache_operation(TEE_CACHEFLUSH, ipi.req, sizeof(cmd->data));
229 
230 	return TEE_SUCCESS;
231 }
232 
versal_mbox_read_rsp(struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * status)233 static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd,
234 				       struct versal_ipi_cmd *rsp,
235 				       uint32_t *status)
236 {
237 	size_t i = 0;
238 
239 	/* Cache operation on the IPI buffer is safe */
240 	cache_operation(TEE_CACHEINVALIDATE, ipi.rsp, sizeof(rsp->data));
241 
242 	*status = *(uint32_t *)ipi.rsp;
243 
244 	if (*status)
245 		return TEE_ERROR_GENERIC;
246 
247 	if (rsp)
248 		memcpy(rsp->data, ipi.rsp, sizeof(rsp->data));
249 
250 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
251 		if (!cmd->ibuf[i].mem.buf)
252 			continue;
253 
254 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
255 				CACHELINE_LEN)) {
256 			EMSG("address not aligned: buffer %zu - %p",
257 			     i, cmd->ibuf[i].mem.buf);
258 			return TEE_ERROR_GENERIC;
259 		}
260 
261 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
262 			EMSG("length not aligned: buffer %zu - %zu",
263 			     i, cmd->ibuf[i].mem.alloc_len);
264 			return TEE_ERROR_GENERIC;
265 		}
266 
267 		cache_operation(TEE_CACHEINVALIDATE,
268 				cmd->ibuf[i].mem.buf,
269 				cmd->ibuf[i].mem.alloc_len);
270 	}
271 
272 	return TEE_SUCCESS;
273 }
274 
versal_mbox_alloc(size_t len,const void * init,struct versal_mbox_mem * mem)275 TEE_Result versal_mbox_alloc(size_t len, const void *init,
276 			     struct versal_mbox_mem *mem)
277 {
278 	mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN));
279 	if (!mem->buf)
280 		panic();
281 
282 	memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN));
283 
284 	if (init)
285 		memcpy(mem->buf, init, len);
286 
287 	mem->alloc_len = ROUNDUP(len, CACHELINE_LEN);
288 	mem->len = len;
289 
290 	return TEE_SUCCESS;
291 }
292 
versal_mbox_notify(struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * err)293 TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd,
294 			      struct versal_ipi_cmd *rsp, uint32_t *err)
295 {
296 	TEE_Result ret = TEE_SUCCESS;
297 	uint32_t remote_status = 0;
298 
299 	mutex_lock(&ipi.lock);
300 
301 	ret = versal_mbox_write_req(cmd);
302 	if (ret) {
303 		EMSG("Can't write the request command");
304 		goto out;
305 	}
306 
307 	if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX))
308 		versal_mbox_call_trace(cmd->data[0]);
309 
310 	ret = mbox_call(IPI_MAILBOX_NOTIFY, IPI_BLOCK);
311 	if (ret) {
312 		EMSG("IPI error");
313 		goto out;
314 	}
315 
316 	ret = versal_mbox_read_rsp(cmd, rsp, &remote_status);
317 	if (ret)
318 		EMSG("Can't read the remote response");
319 
320 	if (remote_status) {
321 		if (err)
322 			*err = remote_status;
323 		/*
324 		 * Check the remote code (FSBL repository) in xplmi_status.h
325 		 * and the relevant service error (ie, xsecure_error.h) for
326 		 * detailed information.
327 		 */
328 		DMSG("PLM: plm status = 0x%" PRIx32 ", lib_status = 0x%" PRIx32,
329 		     (remote_status & 0xFFFF0000) >> 16,
330 		     (remote_status & 0x0000FFFF));
331 
332 		ret = TEE_ERROR_GENERIC;
333 	}
334 out:
335 	mutex_unlock(&ipi.lock);
336 
337 	return ret;
338 }
339 
versal_mbox_init(void)340 static TEE_Result versal_mbox_init(void)
341 {
342 	switch (CFG_VERSAL_MBOX_IPI_ID) {
343 	case 0:
344 		ipi.buf = IPI_BUFFER_APU_ID_0_BASE;
345 		ipi.lcl = IPI_ID_0;
346 		break;
347 	case 3:
348 		break;
349 	case 4:
350 		ipi.buf = IPI_BUFFER_APU_ID_4_BASE;
351 		ipi.lcl = IPI_ID_4;
352 		break;
353 	case 5:
354 		ipi.buf = IPI_BUFFER_APU_ID_5_BASE;
355 		ipi.lcl = IPI_ID_5;
356 		break;
357 	default:
358 		EMSG("Invalid IPI requested");
359 		return TEE_ERROR_GENERIC;
360 	}
361 
362 	ipi.req = core_mmu_add_mapping(MEM_AREA_RAM_SEC,
363 				       ipi.buf + IPI_BUFFER_REMOTE_OFFSET +
364 				       IPI_BUFFER_REQ_OFFSET,
365 				       sizeof(struct versal_ipi_cmd));
366 
367 	ipi.rsp = core_mmu_add_mapping(MEM_AREA_RAM_SEC,
368 				       ipi.buf + IPI_BUFFER_REMOTE_OFFSET +
369 				       IPI_BUFFER_RESP_OFFSET,
370 				       sizeof(struct versal_ipi_cmd));
371 	if (!ipi.req || !ipi.rsp)
372 		panic();
373 
374 	mutex_init(&ipi.lock);
375 
376 	return mbox_call(IPI_MAILBOX_OPEN, IPI_BLOCK);
377 }
378 early_init(versal_mbox_init);
379