77#include <config.h>
88#include <drivers/scmi-msg.h>
99#include <kernel/pseudo_ta.h>
10+ #include <optee_rpc_cmd.h>
1011#include <pta_scmi_client.h>
1112#include <stdint.h>
1213#include <string.h>
14+ #include <tee/uuid.h>
15+ #include <util.h>
16+
17+ static bool valid_caps (unsigned int caps )
18+ {
19+ return (caps & ~PTA_SCMI_CAPS_VALID_MASK ) == 0 ;
20+ }
1321
1422static TEE_Result cmd_capabilities (uint32_t ptypes ,
1523 TEE_Param param [TEE_NUM_PARAMS ])
@@ -25,6 +33,8 @@ static TEE_Result cmd_capabilities(uint32_t ptypes,
2533
2634 if (IS_ENABLED (CFG_SCMI_MSG_SMT ))
2735 caps |= PTA_SCMI_CAPS_SMT_HEADER ;
36+ if (IS_ENABLED (CFG_CORE_OCALL ))
37+ caps |= PTA_SCMI_CAPS_OCALL_THREAD ;
2838
2939 param [0 ].value .a = caps ;
3040 param [0 ].value .b = 0 ;
@@ -97,6 +107,116 @@ static TEE_Result cmd_process_smt_message(uint32_t ptypes,
97107 return TEE_ERROR_NOT_SUPPORTED ;
98108}
99109
110+ /* Process an OCALL RPC to client and report status */
111+ static enum optee_scmi_ocall_reply pta_scmi_ocall (uint32_t channel_id )
112+ {
113+ static const TEE_UUID uuid = PTA_SCMI_UUID ;
114+ static uint64_t uuid_octet [2 ];
115+ static bool uuid_ready ;
116+ struct thread_param params [THREAD_RPC_MAX_NUM_PARAMS ] = {
117+ /* Ocall command, sub command */
118+ THREAD_PARAM_VALUE (INOUT , 0 , 0 , 0 ),
119+ /* UUID of Ocall initiator */
120+ THREAD_PARAM_VALUE (IN , 0 , 0 , 0 ),
121+ /* Output value argument to get REE feedback */
122+ THREAD_PARAM_VALUE (OUT , 0 , 0 , 0 ),
123+ };
124+ uint64_t ocall_res = 0 ;
125+ uint64_t __maybe_unused ocall_ori = 0 ;
126+ enum optee_scmi_ocall_reply agent_request = PTA_SCMI_OCALL_ERROR ;
127+ TEE_Result res = TEE_ERROR_GENERIC ;
128+
129+ if (!IS_ENABLED (CFG_CORE_OCALL ))
130+ return PTA_SCMI_OCALL_ERROR ;
131+
132+ if (!uuid_ready ) {
133+ tee_uuid_to_octets ((uint8_t * )uuid_octet , & uuid );
134+ uuid_ready = true;
135+ }
136+
137+ params [0 ].u .value .a = PTA_SCMI_OCALL_CMD_THREAD_READY ;
138+ params [1 ].u .value .a = uuid_octet [0 ];
139+ params [1 ].u .value .b = uuid_octet [1 ];
140+
141+ params [0 ] = THREAD_PARAM_VALUE (INOUT , PTA_SCMI_OCALL_CMD_THREAD_READY ,
142+ 0 , 0 );
143+ params [1 ] = THREAD_PARAM_VALUE (IN , uuid_octet [0 ], uuid_octet [1 ], 0 );
144+ params [2 ] = THREAD_PARAM_VALUE (OUT , 0 , 0 , 0 );
145+
146+ res = thread_rpc_cmd (OPTEE_RPC_CMD_OCALL , ARRAY_SIZE (params ), params );
147+ if (res ) {
148+ DMSG ("Close thread on RPC error %#" PRIx32 , res );
149+ return PTA_SCMI_OCALL_ERROR ;
150+ }
151+
152+ ocall_res = params [0 ].u .value .b ;
153+ ocall_ori = params [0 ].u .value .c ;
154+ if (ocall_res ) {
155+ DMSG ("SCMI RPC thread failed %#" PRIx64 " from %#" PRIx64 ,
156+ ocall_res , ocall_ori );
157+ return PTA_SCMI_OCALL_ERROR ;
158+ }
159+
160+ agent_request = (enum optee_scmi_ocall_reply )params [2 ].u .value .a ;
161+
162+ switch (agent_request ) {
163+ case PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL :
164+ FMSG ("Posting message on channel %u" PRIu32 , channel_id );
165+ if (IS_ENABLED (CFG_SCMI_MSG_SMT ))
166+ scmi_smt_threaded_entry (channel_id );
167+ else
168+ panic ();
169+ break ;
170+ case PTA_SCMI_OCALL_CLOSE_THREAD :
171+ FMSG ("Closing channel %u" PRIu32 , channel_id );
172+ break ;
173+ case PTA_SCMI_OCALL_ERROR :
174+ FMSG ("Error on channel %u" PRIu32 , channel_id );
175+ break ;
176+ default :
177+ DMSG ("Invalid Ocall cmd %#x on channel %u" PRIu32 ,
178+ agent_request , channel_id );
179+ return PTA_SCMI_OCALL_CLOSE_THREAD ;
180+ }
181+
182+ return agent_request ;
183+ }
184+
185+ static TEE_Result cmd_scmi_ocall_thread (uint32_t ptypes ,
186+ TEE_Param params [TEE_NUM_PARAMS ])
187+ {
188+ const uint32_t exp_ptypes = TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT ,
189+ TEE_PARAM_TYPE_NONE ,
190+ TEE_PARAM_TYPE_NONE ,
191+ TEE_PARAM_TYPE_NONE );
192+
193+ uint32_t channel_id = (int )params [0 ].value .a ;
194+ struct scmi_msg_channel * channel = NULL ;
195+
196+ if (ptypes != exp_ptypes )
197+ return TEE_ERROR_BAD_PARAMETERS ;
198+
199+ if (IS_ENABLED (CFG_SCMI_MSG_SMT ))
200+ channel = plat_scmi_get_channel (channel_id );
201+ else
202+ return TEE_ERROR_NOT_SUPPORTED ;
203+
204+ if (!channel )
205+ return TEE_ERROR_BAD_PARAMETERS ;
206+
207+ FMSG ("Enter Ocall thread on channel %u" PRIu32 , channel_id );
208+ while (1 ) {
209+ switch (pta_scmi_ocall (channel_id )) {
210+ case PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL :
211+ continue ;
212+ case PTA_SCMI_OCALL_CLOSE_THREAD :
213+ return TEE_SUCCESS ;
214+ default :
215+ return TEE_ERROR_GENERIC ;
216+ }
217+ }
218+ }
219+
100220static TEE_Result cmd_get_channel_handle (uint32_t ptypes ,
101221 TEE_Param params [TEE_NUM_PARAMS ])
102222{
@@ -107,13 +227,13 @@ static TEE_Result cmd_get_channel_handle(uint32_t ptypes,
107227 unsigned int channel_id = params [0 ].value .a ;
108228 unsigned int caps = params [0 ].value .b ;
109229
110- if (ptypes != exp_ptypes )
230+ if (ptypes != exp_ptypes || ! valid_caps ( caps ) )
111231 return TEE_ERROR_BAD_PARAMETERS ;
112232
113233 if (IS_ENABLED (CFG_SCMI_MSG_SMT )) {
114234 struct scmi_msg_channel * channel = NULL ;
115235
116- if (caps != PTA_SCMI_CAPS_SMT_HEADER )
236+ if (!( caps & PTA_SCMI_CAPS_SMT_HEADER ) )
117237 return TEE_ERROR_NOT_SUPPORTED ;
118238
119239 channel = plat_scmi_get_channel (channel_id );
@@ -163,6 +283,8 @@ static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd,
163283 return cmd_process_smt_message (ptypes , params );
164284 case PTA_SCMI_CMD_GET_CHANNEL_HANDLE :
165285 return cmd_get_channel_handle (ptypes , params );
286+ case PTA_SCMI_CMD_OCALL_THREAD :
287+ return cmd_scmi_ocall_thread (ptypes , params );
166288 default :
167289 return TEE_ERROR_NOT_SUPPORTED ;
168290 }
0 commit comments