1 /* 2 * Copyright 2017, Rockchip Electronics Co., Ltd 3 * hisping lin, <hisping.lin@rock-chips.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 #include <common.h> 8 #include <optee_include/OpteeClientMem.h> 9 #include <optee_include/OpteeClientSMC.h> 10 #include <optee_include/OpteeClientRPC.h> 11 #include <optee_include/teesmc.h> 12 13 #define TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES \ 14 (TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT); 15 16 static void SetTeeSmc32Params(TEEC_Operation *operation, 17 t_teesmc32_param *TeeSmc32Param); 18 static void GetTeeSmc32Params(t_teesmc32_param *TeeSmc32Param, 19 TEEC_Operation *operation); 20 static TEEC_Result OpteeSmcCall(t_teesmc32_arg *TeeSmc32Arg); 21 22 /* 23 * This function opens a new Session between the Client application and the 24 * specified TEE application. 25 * 26 * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and 27 * operation shall be set to NULL. 28 */ 29 TEEC_Result TEEC_SMC_OpenSession(TEEC_Context *context, 30 TEEC_Session *session, 31 const TEEC_UUID *destination, 32 TEEC_Operation *operation, 33 uint32_t *error_origin) 34 { 35 TEEC_Result TeecResult = TEEC_SUCCESS; 36 uint32_t TeeSmc32ArgLength; 37 uint32_t TeeSmcMetaSessionLength; 38 39 t_teesmc32_arg *TeeSmc32Arg = NULL; 40 t_teesmc32_param *TeeSmc32Param = NULL; 41 t_teesmc_meta_open_session *TeeSmcMetaSession = NULL; 42 static const uint32_t MetaNum = 1; 43 44 *error_origin = TEEC_ORIGIN_API; 45 46 TeeSmc32ArgLength = 47 TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT + MetaNum); 48 49 TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength); 50 51 if (TeeSmc32Arg == NULL) { 52 TeecResult = TEEC_ERROR_OUT_OF_MEMORY; 53 goto Exit; 54 } 55 56 memset(TeeSmc32Arg, 0, TeeSmc32ArgLength); 57 58 TeeSmcMetaSessionLength = sizeof(*TeeSmcMetaSession); 59 60 TeeSmcMetaSession = (t_teesmc_meta_open_session *) 61 OpteeClientMemAlloc(TeeSmcMetaSessionLength); 62 63 if (TeeSmcMetaSession == NULL) { 64 TeecResult = TEEC_ERROR_OUT_OF_MEMORY; 65 goto Exit; 66 } 67 68 memset(TeeSmcMetaSession, 0, TeeSmcMetaSessionLength); 69 70 TeeSmc32Arg->cmd = TEESMC_CMD_OPEN_SESSION; 71 TeeSmc32Arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT + MetaNum; 72 73 TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg); 74 75 memcpy(&TeeSmcMetaSession->uuid, 76 destination, 77 sizeof(TeeSmcMetaSession->uuid)); 78 TeeSmcMetaSession->clnt_login = TEEC_LOGIN_PUBLIC; 79 80 TeeSmc32Param[0].u.memref.buf_ptr = (uint32_t) TeeSmcMetaSession; 81 TeeSmc32Param[0].u.memref.size = sizeof(*TeeSmcMetaSession); 82 83 #ifdef CONFIG_ROCKCHIP_RK3328 84 TeeSmc32Param[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | 85 TEESMC_ATTR_META | 86 TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES; 87 #endif 88 89 #ifdef CONFIG_ROCKCHIP_RK322X 90 TeeSmc32Param[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | 91 TEESMC_ATTR_META; 92 #endif 93 94 SetTeeSmc32Params(operation, TeeSmc32Param + MetaNum); 95 96 *error_origin = TEEC_ORIGIN_COMMS; 97 98 TeecResult = OpteeSmcCall(TeeSmc32Arg); 99 if (TeecResult != TEEC_SUCCESS) 100 goto Exit; 101 102 session->id = TeeSmc32Arg->session; 103 TeecResult = TeeSmc32Arg->ret; 104 *error_origin = TeeSmc32Arg->ret_origin; 105 106 GetTeeSmc32Params(TeeSmc32Param + MetaNum, operation); 107 108 Exit: 109 if (TeeSmc32Arg != NULL) 110 OpteeClientMemFree(TeeSmc32Arg); 111 112 if (TeeSmcMetaSession != NULL) 113 OpteeClientMemFree(TeeSmcMetaSession); 114 115 return TeecResult; 116 } 117 118 /* 119 * This function closes a session which has been opened with a TEE 120 * application. 121 * 122 * Note that the GP specification does not allow for this API to fail and return 123 * a failure code however we'll support this at the SMC level so we can get 124 * see debug information about such failures. 125 */ 126 TEEC_Result TEEC_SMC_CloseSession(TEEC_Session *session, 127 uint32_t *error_origin) 128 { 129 TEEC_Result TeecResult = TEEC_SUCCESS; 130 uint32_t TeeSmc32ArgLength; 131 t_teesmc32_arg *TeeSmc32Arg = NULL; 132 133 *error_origin = TEEC_ORIGIN_API; 134 135 TeeSmc32ArgLength = 136 TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT); 137 138 TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength); 139 140 if (TeeSmc32Arg == NULL) { 141 TeecResult = TEEC_ERROR_OUT_OF_MEMORY; 142 goto Exit; 143 } 144 145 memset(TeeSmc32Arg, 0, TeeSmc32ArgLength); 146 147 TeeSmc32Arg->cmd = TEESMC_CMD_CLOSE_SESSION; 148 TeeSmc32Arg->session = session->id; 149 150 *error_origin = TEEC_ORIGIN_COMMS; 151 152 TeecResult = OpteeSmcCall(TeeSmc32Arg); 153 154 if (TeecResult != TEEC_SUCCESS) 155 goto Exit; 156 157 TeecResult = TeeSmc32Arg->ret; 158 *error_origin = TeeSmc32Arg->ret_origin; 159 160 Exit: 161 if (TeeSmc32Arg != NULL) 162 OpteeClientMemFree(TeeSmc32Arg); 163 164 return TeecResult; 165 } 166 167 /* 168 * Invokes a TEE command (secure service, sub-PA or whatever). 169 */ 170 TEEC_Result TEEC_SMC_InvokeCommand(TEEC_Session *session, 171 uint32_t cmd_id, 172 TEEC_Operation *operation, 173 uint32_t *error_origin) 174 { 175 TEEC_Result TeecResult = TEEC_SUCCESS; 176 uint32_t TeeSmc32ArgLength; 177 t_teesmc32_arg *TeeSmc32Arg = NULL; 178 t_teesmc32_param *TeeSmc32Param = NULL; 179 180 *error_origin = TEEC_ORIGIN_API; 181 182 TeeSmc32ArgLength = 183 TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT); 184 185 TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength); 186 187 if (TeeSmc32Arg == NULL) { 188 TeecResult = TEEC_ERROR_OUT_OF_MEMORY; 189 goto Exit; 190 } 191 192 memset(TeeSmc32Arg, 0, TeeSmc32ArgLength); 193 194 TeeSmc32Arg->cmd = TEESMC_CMD_INVOKE_COMMAND; 195 TeeSmc32Arg->ta_func = cmd_id; 196 TeeSmc32Arg->session = session->id; 197 TeeSmc32Arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; 198 199 TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg); 200 201 SetTeeSmc32Params(operation, TeeSmc32Param); 202 203 *error_origin = TEEC_ORIGIN_COMMS; 204 205 TeecResult = OpteeSmcCall(TeeSmc32Arg); 206 if (TeecResult != TEEC_SUCCESS) 207 goto Exit; 208 209 TeecResult = TeeSmc32Arg->ret; 210 *error_origin = TeeSmc32Arg->ret_origin; 211 212 GetTeeSmc32Params(TeeSmc32Param, operation); 213 214 Exit: 215 if (TeeSmc32Arg != NULL) 216 OpteeClientMemFree(TeeSmc32Arg); 217 218 219 return TeecResult; 220 } 221 222 /* 223 * Request a cancellation of a in-progress operation (best effort) 224 * 225 * Note that the GP specification does not allow for this API to fail and return 226 * a failure code however we'll support this at the SMC level so we can get 227 * see debug information about such failures. 228 */ 229 TEEC_Result TEEC_SMC_RequestCancellation(TEEC_Operation *operation, 230 uint32_t *error_origin) 231 { 232 return TEEC_ERROR_NOT_IMPLEMENTED; 233 } 234 235 /* 236 * Set the call parameter blocks in the 237 * SMC call based on the TEEC parameter supplied. 238 * This only handles the parameters supplied in 239 * the originating call and not those 240 * considered internal meta parameters and is 241 * thus constrained by the build 242 * constants exposed to callers. 243 */ 244 void SetTeeSmc32Params(TEEC_Operation *operation, 245 t_teesmc32_param *TeeSmc32Param) 246 { 247 uint32_t ParamCount; 248 249 for (ParamCount = 0; 250 ParamCount < TEEC_CONFIG_PAYLOAD_REF_COUNT; 251 ParamCount++) { 252 uint32_t attr = 253 TEEC_PARAM_TYPE_GET(operation->paramTypes, ParamCount); 254 255 if (attr == TEEC_MEMREF_TEMP_INPUT || 256 attr == TEEC_MEMREF_TEMP_OUTPUT || 257 attr == TEEC_MEMREF_TEMP_INOUT) { 258 #ifdef CONFIG_ROCKCHIP_RK3328 259 attr |= TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES; 260 debug(" 3328 attr %x\n", attr); 261 #endif 262 #ifdef CONFIG_ROCKCHIP_RK322X 263 debug(" 322X attr %x\n", attr); 264 #endif 265 TeeSmc32Param[ParamCount].attr = attr; 266 TeeSmc32Param[ParamCount].u.memref.buf_ptr = 267 (uint32_t)operation->params[ParamCount].tmpref.buffer; 268 TeeSmc32Param[ParamCount].u.memref.size = 269 operation->params[ParamCount].tmpref.size; 270 } else { 271 TeeSmc32Param[ParamCount].attr = attr; 272 TeeSmc32Param[ParamCount].u.value.a = 273 operation->params[ParamCount].value.a; 274 TeeSmc32Param[ParamCount].u.value.b = 275 operation->params[ParamCount].value.b; 276 } 277 } 278 } 279 280 /* 281 * Get the return parameter blocks from 282 * the SMC call into the TEEC parameter supplied. 283 * This only handles the parameters supplied 284 * in the originating call and not those 285 * considered internal meta parameters and 286 * is thus constrained by the build 287 * constants exposed to callers. 288 */ 289 void GetTeeSmc32Params(t_teesmc32_param *TeeSmc32Param, 290 TEEC_Operation *operation) 291 { 292 uint32_t ParamCount; 293 294 for (ParamCount = 0; 295 ParamCount < TEEC_CONFIG_PAYLOAD_REF_COUNT; 296 ParamCount++) { 297 operation->params[ParamCount].value.a = 298 TeeSmc32Param[ParamCount].u.value.a; 299 operation->params[ParamCount].value.b = 300 TeeSmc32Param[ParamCount].u.value.b; 301 } 302 } 303 304 /* 305 * Populate the SMC registers and make 306 * the call with OpTEE specific handling. 307 */ 308 TEEC_Result OpteeSmcCall(t_teesmc32_arg *TeeSmc32Arg) 309 { 310 TEEC_Result TeecResult = TEEC_SUCCESS; 311 ARM_SMC_ARGS ArmSmcArgs = {0}; 312 313 ArmSmcArgs.Arg0 = TEESMC32_CALL_WITH_ARG; 314 ArmSmcArgs.Arg1 = (uint32_t) TeeSmc32Arg; 315 316 while (1) { 317 tee_smc_call(&ArmSmcArgs); 318 319 if (TEESMC_RETURN_IS_RPC(ArmSmcArgs.Arg0)) { 320 (void) OpteeRpcCallback(&ArmSmcArgs); 321 } else if (ArmSmcArgs.Arg0 == TEESMC_RETURN_UNKNOWN_FUNCTION) { 322 TeecResult = TEEC_ERROR_NOT_IMPLEMENTED; 323 break; 324 } else if (ArmSmcArgs.Arg0 != TEESMC_RETURN_OK) { 325 TeecResult = TEEC_ERROR_COMMUNICATION; 326 break; 327 } else { 328 TeecResult = TEEC_SUCCESS; 329 break; 330 } 331 } 332 333 return TeecResult; 334 } 335 336