1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019-2021, Linaro Limited 4 * Copyright (c) 2019-2021, STMicroelectronics 5 */ 6 #include <compiler.h> 7 #include <config.h> 8 #include <drivers/scmi-msg.h> 9 #include <kernel/pseudo_ta.h> 10 #include <pta_scmi_client.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 static TEE_Result cmd_capabilities(uint32_t ptypes, 15 TEE_Param param[TEE_NUM_PARAMS]) 16 { 17 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 18 TEE_PARAM_TYPE_NONE, 19 TEE_PARAM_TYPE_NONE, 20 TEE_PARAM_TYPE_NONE); 21 uint32_t caps = 0; 22 23 if (ptypes != exp_ptypes) 24 return TEE_ERROR_BAD_PARAMETERS; 25 26 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 27 caps |= PTA_SCMI_CAPS_SMT_HEADER; 28 if (IS_ENABLED(CFG_SCMI_MSG_SHM_MSG)) 29 caps |= PTA_SCMI_CAPS_MSG_HEADER; 30 31 param[0].value.a = caps; 32 param[0].value.b = 0; 33 34 return TEE_SUCCESS; 35 } 36 37 static TEE_Result cmd_process_smt_channel(uint32_t ptypes, 38 TEE_Param params[TEE_NUM_PARAMS]) 39 { 40 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 41 TEE_PARAM_TYPE_NONE, 42 TEE_PARAM_TYPE_NONE, 43 TEE_PARAM_TYPE_NONE); 44 unsigned int channel_id = params[0].value.a; 45 46 if (ptypes != exp_ptypes) 47 return TEE_ERROR_BAD_PARAMETERS; 48 49 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 50 struct scmi_msg_channel *channel = NULL; 51 52 channel = plat_scmi_get_channel(channel_id); 53 if (!channel) 54 return TEE_ERROR_BAD_PARAMETERS; 55 56 scmi_smt_threaded_entry(channel_id); 57 58 return TEE_SUCCESS; 59 } 60 61 return TEE_ERROR_NOT_SUPPORTED; 62 } 63 64 static TEE_Result cmd_process_smt_message(uint32_t ptypes, 65 TEE_Param params[TEE_NUM_PARAMS]) 66 { 67 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 68 TEE_PARAM_TYPE_MEMREF_INOUT, 69 TEE_PARAM_TYPE_NONE, 70 TEE_PARAM_TYPE_NONE); 71 unsigned int channel_id = params[0].value.a; 72 TEE_Param *param1 = params + 1; 73 74 if (ptypes != exp_ptypes) 75 return TEE_ERROR_BAD_PARAMETERS; 76 77 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 78 struct scmi_msg_channel *channel = NULL; 79 80 if (param1->memref.size < SMT_BUF_SLOT_SIZE) 81 return TEE_ERROR_BAD_PARAMETERS; 82 83 channel = plat_scmi_get_channel(channel_id); 84 if (!channel) 85 return TEE_ERROR_BAD_PARAMETERS; 86 87 /* 88 * Caller provides the buffer, we bind channel to that buffer. 89 * Once message is processed, unbind the buffer since it is 90 * valid only for the current invocation. 91 */ 92 scmi_smt_set_shared_buffer(channel, param1->memref.buffer); 93 scmi_smt_threaded_entry(channel_id); 94 scmi_smt_set_shared_buffer(channel, NULL); 95 96 return TEE_SUCCESS; 97 } 98 99 return TEE_ERROR_NOT_SUPPORTED; 100 } 101 102 static TEE_Result cmd_process_msg_channel(uint32_t ptypes, 103 TEE_Param params[TEE_NUM_PARAMS]) 104 { 105 TEE_Result res = TEE_ERROR_GENERIC; 106 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 107 TEE_PARAM_TYPE_MEMREF_INPUT, 108 TEE_PARAM_TYPE_MEMREF_OUTPUT, 109 TEE_PARAM_TYPE_NONE); 110 unsigned int channel_id = params[0].value.a; 111 void *in_buf = params[1].memref.buffer; 112 size_t in_size = params[1].memref.size; 113 void *out_buf = params[2].memref.buffer; 114 size_t out_size = params[2].memref.size; 115 116 if (ptypes != exp_pt || !in_buf || !out_buf) 117 return TEE_ERROR_BAD_PARAMETERS; 118 119 if (IS_ENABLED(CFG_SCMI_MSG_SHM_MSG)) { 120 struct scmi_msg_channel *channel = NULL; 121 122 channel = plat_scmi_get_channel(channel_id); 123 if (!channel) 124 return TEE_ERROR_BAD_PARAMETERS; 125 126 res = scmi_msg_threaded_entry(channel_id, in_buf, in_size, 127 out_buf, &out_size); 128 if (!res) 129 params[2].memref.size = out_size; 130 131 return res; 132 } 133 134 return TEE_ERROR_NOT_SUPPORTED; 135 } 136 137 static TEE_Result cmd_get_channel_handle(uint32_t ptypes, 138 TEE_Param params[TEE_NUM_PARAMS]) 139 { 140 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, 141 TEE_PARAM_TYPE_NONE, 142 TEE_PARAM_TYPE_NONE, 143 TEE_PARAM_TYPE_NONE); 144 unsigned int channel_id = params[0].value.a; 145 unsigned int caps = params[0].value.b; 146 const unsigned int supported_caps = PTA_SCMI_CAPS_SMT_HEADER | 147 PTA_SCMI_CAPS_MSG_HEADER; 148 149 if (ptypes != exp_ptypes || caps & ~supported_caps) 150 return TEE_ERROR_BAD_PARAMETERS; 151 152 if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { 153 struct scmi_msg_channel *channel = NULL; 154 155 if (!IS_ENABLED(CFG_SCMI_MSG_SMT) && 156 caps & PTA_SCMI_CAPS_SMT_HEADER) 157 return TEE_ERROR_NOT_SUPPORTED; 158 159 channel = plat_scmi_get_channel(channel_id); 160 if (!channel) 161 return TEE_ERROR_BAD_PARAMETERS; 162 163 channel->threaded = true; 164 params[0].value.a = scmi_smt_channel_handle(channel_id); 165 166 return TEE_SUCCESS; 167 } 168 169 return TEE_ERROR_NOT_SUPPORTED; 170 } 171 172 static TEE_Result pta_scmi_open_session(uint32_t ptypes __unused, 173 TEE_Param par[TEE_NUM_PARAMS] __unused, 174 void **session __unused) 175 { 176 struct ts_session *ts = ts_get_current_session(); 177 struct tee_ta_session *ta_session = to_ta_session(ts); 178 179 /* Only REE kernel is allowed to access SCMI resources */ 180 if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) { 181 DMSG("Expecting TEE_LOGIN_REE_KERNEL"); 182 return TEE_ERROR_ACCESS_DENIED; 183 } 184 185 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 186 return TEE_SUCCESS; 187 188 return TEE_ERROR_NOT_SUPPORTED; 189 } 190 191 static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd, 192 uint32_t ptypes, 193 TEE_Param params[TEE_NUM_PARAMS]) 194 { 195 FMSG("SCMI command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); 196 197 switch (cmd) { 198 case PTA_SCMI_CMD_CAPABILITIES: 199 return cmd_capabilities(ptypes, params); 200 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL: 201 return cmd_process_smt_channel(ptypes, params); 202 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE: 203 return cmd_process_smt_message(ptypes, params); 204 case PTA_SCMI_CMD_PROCESS_MSG_CHANNEL: 205 return cmd_process_msg_channel(ptypes, params); 206 case PTA_SCMI_CMD_GET_CHANNEL_HANDLE: 207 return cmd_get_channel_handle(ptypes, params); 208 default: 209 return TEE_ERROR_NOT_SUPPORTED; 210 } 211 } 212 213 pseudo_ta_register(.uuid = PTA_SCMI_UUID, .name = PTA_SCMI_NAME, 214 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | 215 TA_FLAG_DEVICE_ENUM, 216 .open_session_entry_point = pta_scmi_open_session, 217 .invoke_command_entry_point = pta_scmi_invoke_command); 218