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