1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
4 * Copyright 2017-2021 NXP
5 */
6 #include <drivers/imx_mu.h>
7 #include <drivers/imx_sc_api.h>
8 #include <imx-regs.h>
9 #include <initcall.h>
10 #include <kernel/mutex.h>
11 #include <mm/core_memprot.h>
12 #include <tee_api_types.h>
13 #include <trace.h>
14
15 #define RNG_INIT_RETRY 100
16
17 #define SC_RPC_VERSION 1
18 #define SC_RPC_MAX_MSG 8
19
20 /* Macros to fill struct sc_rpc_msg data field */
21 #define RPC_U32(mesg, idx) ((mesg)->data.u32[(idx)])
22 #define RPC_U16(mesg, idx) ((mesg)->data.u16[(idx)])
23 #define RPC_U8(mesg, idx) ((mesg)->data.u8[(idx)])
24
25 /* Defines for struct sc_rpc_msg svc field */
26 #define SC_RPC_SVC_PM 2
27 #define SC_RPC_SVC_RM 3
28 #define SC_RPC_SVC_SECO 9
29
30 /* Define for PM function calls */
31 enum sc_pm_func {
32 SC_PM_FUNC_SET_RESOURCE_POWER_MODE = 3
33 };
34
35 /* Defines for RM function calls */
36 enum sc_rm_func {
37 SC_RM_FUNC_GET_PARTITION = 5,
38 SC_RM_FUNC_ASSIGN_RESOURCE = 8
39 };
40
41 /* Define for SECO function calls */
42 enum sc_seco_func {
43 SC_SECO_FUNC_START_RNG = 22
44 };
45
46 /* Internal SCFW API error codes */
47 enum sc_error {
48 SC_ERR_NONE = 0, /* Success */
49 SC_ERR_VERSION, /* Incompatible API version */
50 SC_ERR_CONFIG, /* Configuration error */
51 SC_ERR_PARM, /* Bad parameter */
52 SC_ERR_NOACCESS, /* Permission error (no access) */
53 SC_ERR_LOCKED, /* Permission error (locked) */
54 SC_ERR_UNAVAILABLE, /* Unavailable (out of resources) */
55 SC_ERR_NOTFOUND, /* Not found */
56 SC_ERR_NOPOWER, /* No power */
57 SC_ERR_IPC, /* Generic IPC error */
58 SC_ERR_BUSY, /* Resource is currently busy/active */
59 SC_ERR_FAIL, /* General I/O failure */
60 SC_ERR_LAST
61 };
62
63 /* RNG SECO states */
64 enum sc_seco_rng_status {
65 SC_SECO_RNG_STAT_UNAVAILABLE = 0,
66 SC_SECO_RNG_STAT_INPROGRESS,
67 SC_SECO_RNG_STAT_READY
68 };
69
70 /* Resources IDs */
71 enum sc_resource {
72 SC_RES_CAAM_JR1 = 500,
73 SC_RES_CAAM_JR2,
74 SC_RES_CAAM_JR3,
75 SC_RES_CAAM_JR1_OUT = 514,
76 SC_RES_CAAM_JR2_OUT,
77 SC_RES_CAAM_JR3_OUT,
78 SC_RES_CAAM_JR0 = 519,
79 SC_RES_CAAM_JR0_OUT,
80 SC_RES_LAST = 546
81 };
82
83 /* Power modes */
84 enum sc_power_mode {
85 SC_PM_PW_MODE_OFF = 0,
86 SC_PM_PW_MODE_STBY,
87 SC_PM_PW_MODE_LP,
88 SC_PM_PW_MODE_ON
89 };
90
91 /* RPC message header */
92 struct sc_rpc_msg_header {
93 uint8_t version; /* SC RPC version */
94 uint8_t size; /* Size of the message */
95 uint8_t svc; /* Type of service: one of SC_RPC_SVC_* */
96 uint8_t func; /* Function ID or Error code */
97 };
98
99 /* RPC message format */
100 struct sc_rpc_msg {
101 struct sc_rpc_msg_header header;
102 union {
103 uint32_t u32[SC_RPC_MAX_MSG - 1];
104 uint16_t u16[(SC_RPC_MAX_MSG - 1) * 2];
105 uint8_t u8[(SC_RPC_MAX_MSG - 1) * 4];
106 } data;
107 };
108
109 static struct mutex scu_mu_mutex = MUTEX_INITIALIZER;
110 static vaddr_t secure_ipc_addr;
111
112 register_phys_mem(MEM_AREA_IO_SEC, SC_IPC_BASE_SECURE, SC_IPC_SIZE);
113
114 /*
115 * Read a message from an IPC channel
116 *
117 * @ipc IPC channel
118 * @msg Received message
119 */
sc_ipc_read(vaddr_t ipc,struct sc_rpc_msg * msg)120 static TEE_Result sc_ipc_read(vaddr_t ipc, struct sc_rpc_msg *msg)
121 {
122 TEE_Result res = TEE_ERROR_GENERIC;
123 unsigned int count = 0;
124
125 if (!msg) {
126 EMSG("msg is NULL");
127 return TEE_ERROR_BAD_PARAMETERS;
128 }
129
130 assert(ipc);
131
132 res = mu_receive_msg(ipc, 0, (uint32_t *)msg);
133 if (res)
134 return res;
135
136 /* Check the size of the message to receive */
137 if (msg->header.size > SC_RPC_MAX_MSG) {
138 EMSG("Size of the message is > than SC_RPC_MAX_MSG");
139 return TEE_ERROR_BAD_FORMAT;
140 }
141
142 for (count = 1; count < msg->header.size; count++) {
143 res = mu_receive_msg(ipc, count % MU_NB_RR,
144 &msg->data.u32[count - 1]);
145 if (res)
146 return res;
147 }
148
149 return TEE_SUCCESS;
150 }
151
152 /*
153 * Write a message to an IPC channel
154 *
155 * @ipc IPC channel
156 * @msg Send message pointer
157 */
sc_ipc_write(vaddr_t ipc,struct sc_rpc_msg * msg)158 static TEE_Result sc_ipc_write(vaddr_t ipc, struct sc_rpc_msg *msg)
159 {
160 TEE_Result res = TEE_ERROR_GENERIC;
161 unsigned int count = 0;
162
163 if (!msg) {
164 EMSG("msg is NULL");
165 return TEE_ERROR_BAD_PARAMETERS;
166 }
167
168 if (msg->header.size > SC_RPC_MAX_MSG) {
169 EMSG("msg->size is > than SC_RPC_MAX_MSG");
170 return TEE_ERROR_BAD_FORMAT;
171 }
172
173 assert(ipc);
174
175 res = mu_send_msg(ipc, 0, *(uint32_t *)msg);
176 if (res)
177 return res;
178
179 for (count = 1; count < msg->header.size; count++) {
180 res = mu_send_msg(ipc, count % MU_NB_TR,
181 msg->data.u32[count - 1]);
182 if (res)
183 return res;
184 }
185
186 return TEE_SUCCESS;
187 }
188
189 /*
190 * Send an RPC message over the secure world IPC channel
191 *
192 * @msg Message to send. This pointer will also return the answer
193 * message if expected.
194 * @wait_resp Set to true if an answer is expected.
195 */
sc_call_rpc(struct sc_rpc_msg * msg,bool wait_resp)196 static TEE_Result sc_call_rpc(struct sc_rpc_msg *msg, bool wait_resp)
197 {
198 TEE_Result res = TEE_ERROR_GENERIC;
199
200 mutex_lock(&scu_mu_mutex);
201
202 res = sc_ipc_write(secure_ipc_addr, msg);
203
204 if (res == TEE_SUCCESS && wait_resp)
205 res = sc_ipc_read(secure_ipc_addr, msg);
206
207 mutex_unlock(&scu_mu_mutex);
208
209 return res;
210 }
211
212 /*
213 * Get the partition ID of secure world
214 *
215 * @partition Partition ID
216 */
sc_rm_get_partition(uint8_t * partition)217 static TEE_Result sc_rm_get_partition(uint8_t *partition)
218 {
219 TEE_Result res = TEE_ERROR_GENERIC;
220 enum sc_error err = SC_ERR_LAST;
221 struct sc_rpc_msg msg = {
222 .header.version = SC_RPC_VERSION,
223 .header.size = 1,
224 .header.svc = SC_RPC_SVC_RM,
225 .header.func = SC_RM_FUNC_GET_PARTITION,
226 };
227
228 res = sc_call_rpc(&msg, true);
229 if (res != TEE_SUCCESS) {
230 EMSG("Communication error");
231 return res;
232 }
233
234 err = msg.header.func;
235 if (err != SC_ERR_NONE) {
236 EMSG("Unable to get partition ID, sc_error: %d", err);
237 return TEE_ERROR_GENERIC;
238 }
239
240 *partition = RPC_U8(&msg, 0);
241
242 return TEE_SUCCESS;
243 }
244
245 /*
246 * Set the given power mode of a resource
247 *
248 * @resource ID of the resource
249 * @mode Power mode to apply
250 */
sc_pm_set_resource_power_mode(enum sc_resource resource,enum sc_power_mode mode)251 static TEE_Result sc_pm_set_resource_power_mode(enum sc_resource resource,
252 enum sc_power_mode mode)
253 {
254 TEE_Result res = TEE_ERROR_GENERIC;
255 enum sc_error scu_error = SC_ERR_LAST;
256 struct sc_rpc_msg msg = {
257 .header.version = SC_RPC_VERSION,
258 .header.size = 2,
259 .header.svc = SC_RPC_SVC_PM,
260 .header.func = SC_PM_FUNC_SET_RESOURCE_POWER_MODE,
261 };
262
263 RPC_U16(&msg, 0) = (uint16_t)resource;
264 RPC_U8(&msg, 2) = (uint8_t)mode;
265
266 res = sc_call_rpc(&msg, true);
267 if (res != TEE_SUCCESS) {
268 EMSG("Communication error");
269 return res;
270 }
271
272 scu_error = msg.header.func;
273 if (scu_error != SC_ERR_NONE) {
274 EMSG("Unable to set resource power mode sc_error: %d",
275 scu_error);
276 return TEE_ERROR_GENERIC;
277 }
278
279 return TEE_SUCCESS;
280 }
281
282 /*
283 * Assign ownership of a resource to the secure partition
284 *
285 * @resource Resource to assign
286 */
sc_rm_assign_resource(enum sc_resource resource)287 static TEE_Result sc_rm_assign_resource(enum sc_resource resource)
288 {
289 TEE_Result res = TEE_ERROR_GENERIC;
290 enum sc_error err = SC_ERR_LAST;
291 uint8_t secure_partition = 0;
292 struct sc_rpc_msg msg = {
293 .header.version = SC_RPC_VERSION,
294 .header.size = 2,
295 .header.svc = SC_RPC_SVC_RM,
296 .header.func = SC_RM_FUNC_ASSIGN_RESOURCE,
297 };
298
299 res = sc_rm_get_partition(&secure_partition);
300 if (res != TEE_SUCCESS) {
301 EMSG("Cannot get secure partition ID");
302 return res;
303 }
304
305 RPC_U16(&msg, 0) = (uint16_t)resource;
306 RPC_U8(&msg, 2) = secure_partition;
307
308 res = sc_call_rpc(&msg, true);
309 if (res != TEE_SUCCESS) {
310 EMSG("Communication error");
311 return res;
312 }
313
314 err = msg.header.func;
315 if (err != SC_ERR_NONE) {
316 EMSG("Unable to assign resource, sc_error: %d", err);
317 return TEE_ERROR_GENERIC;
318 }
319
320 return TEE_SUCCESS;
321 }
322
imx_sc_rm_enable_jr(unsigned int jr_index)323 TEE_Result imx_sc_rm_enable_jr(unsigned int jr_index)
324 {
325 TEE_Result res = TEE_ERROR_GENERIC;
326 enum sc_resource jr_res = SC_RES_LAST;
327 enum sc_resource jr_out_res = SC_RES_LAST;
328
329 switch (jr_index) {
330 case 0:
331 jr_res = SC_RES_CAAM_JR0;
332 jr_out_res = SC_RES_CAAM_JR0_OUT;
333 break;
334
335 case 1:
336 jr_res = SC_RES_CAAM_JR1;
337 jr_out_res = SC_RES_CAAM_JR1_OUT;
338 break;
339
340 case 2:
341 jr_res = SC_RES_CAAM_JR2;
342 jr_out_res = SC_RES_CAAM_JR2_OUT;
343 break;
344
345 case 3:
346 jr_res = SC_RES_CAAM_JR3;
347 jr_out_res = SC_RES_CAAM_JR3_OUT;
348 break;
349
350 default:
351 EMSG("Wrong JR Index, should be 0, 1, 2 or 3");
352 return TEE_ERROR_GENERIC;
353 }
354
355 /* Assign JR resources to secure world */
356 res = sc_rm_assign_resource(jr_res);
357 if (res != TEE_SUCCESS) {
358 EMSG("Assign SC_R_CAAM_JR%u resource failed", jr_index);
359 return res;
360 }
361
362 res = sc_rm_assign_resource(jr_out_res);
363 if (res != TEE_SUCCESS) {
364 EMSG("Assign SC_R_CAAM_JR%u_OUT resource failed", jr_index);
365 return res;
366 }
367
368 /* Power ON JR resources */
369 res = sc_pm_set_resource_power_mode(jr_res, SC_PM_PW_MODE_ON);
370 if (res != TEE_SUCCESS) {
371 EMSG("POWER ON SC_R_CAAM_JR%u resource failed", jr_index);
372 return res;
373 }
374
375 res = sc_pm_set_resource_power_mode(jr_out_res, SC_PM_PW_MODE_ON);
376 if (res != TEE_SUCCESS) {
377 EMSG("POWER ON SC_R_CAAM_JR%u_OUT resource failed", jr_index);
378 return res;
379 }
380
381 return TEE_SUCCESS;
382 }
383
imx_sc_seco_start_rng(void)384 TEE_Result imx_sc_seco_start_rng(void)
385 {
386 TEE_Result res = TEE_ERROR_GENERIC;
387 enum sc_error err = SC_ERR_LAST;
388 enum sc_seco_rng_status status = SC_SECO_RNG_STAT_UNAVAILABLE;
389 unsigned int retry = 0;
390 struct sc_rpc_msg msg = {
391 .header.version = SC_RPC_VERSION,
392 .header.size = 1,
393 .header.svc = SC_RPC_SVC_SECO,
394 .header.func = SC_SECO_FUNC_START_RNG,
395 };
396
397 for (retry = RNG_INIT_RETRY; retry; retry--) {
398 res = sc_call_rpc(&msg, true);
399 if (res != TEE_SUCCESS) {
400 EMSG("Configuration error");
401 return res;
402 }
403
404 err = msg.header.func;
405 if (err != SC_ERR_NONE) {
406 EMSG("RNG status: %d", err);
407 return TEE_ERROR_GENERIC;
408 }
409
410 status = RPC_U32(&msg, 0);
411
412 if (status == SC_SECO_RNG_STAT_READY)
413 return TEE_SUCCESS;
414 }
415
416 return TEE_ERROR_GENERIC;
417 }
418
imx_sc_driver_init(void)419 TEE_Result imx_sc_driver_init(void)
420 {
421 vaddr_t va = 0;
422
423 va = core_mmu_get_va(SC_IPC_BASE_SECURE, MEM_AREA_IO_SEC, SC_IPC_SIZE);
424 if (!va)
425 return TEE_ERROR_GENERIC;
426
427 mutex_lock(&scu_mu_mutex);
428 mu_init(va);
429 secure_ipc_addr = va;
430 mutex_unlock(&scu_mu_mutex);
431
432 return TEE_SUCCESS;
433 }
434