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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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