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