1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
4  */
5 
6 #include "ffa_api.h"
7 #include "sp_api_defines.h"
8 #include "sp_messaging.h"
9 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
10 #include "ffa_direct_msg_routing_extension.h"
11 #endif
12 
13 #include <string.h>
14 
pack_ffa_direct_msg(const struct sp_msg * msg,struct ffa_direct_msg * ffa_msg)15 static void pack_ffa_direct_msg(const struct sp_msg *msg,
16 				struct ffa_direct_msg *ffa_msg)
17 {
18 	ffa_msg->source_id = msg->source_id;
19 	ffa_msg->destination_id = msg->destination_id;
20 
21 	if (msg->is_64bit_message) {
22 		ffa_msg->function_id = FFA_TO_64_BIT_FUNC(0);
23 		memcpy(ffa_msg->args.args64, msg->args.args64, sizeof(msg->args.args64));
24 	} else {
25 		memcpy(ffa_msg->args.args32, msg->args.args32, sizeof(msg->args.args32));
26 	}
27 }
28 
unpack_ffa_direct_msg(const struct ffa_direct_msg * ffa_msg,struct sp_msg * msg)29 static void unpack_ffa_direct_msg(const struct ffa_direct_msg *ffa_msg,
30 				  struct sp_msg *msg)
31 {
32 	if (ffa_msg->function_id == FFA_MSG_SEND_DIRECT_REQ_32 ||
33 	    ffa_msg->function_id == FFA_MSG_SEND_DIRECT_RESP_32) {
34 		/*
35 		 * Handling 32 bit request or response
36 		 */
37 		msg->source_id = ffa_msg->source_id;
38 		msg->destination_id = ffa_msg->destination_id;
39 		msg->is_64bit_message = false;
40 
41 		memcpy(msg->args.args32, ffa_msg->args.args32, sizeof(msg->args.args32));
42 	} else if (ffa_msg->function_id == FFA_MSG_SEND_DIRECT_REQ_64 ||
43 		   ffa_msg->function_id == FFA_MSG_SEND_DIRECT_RESP_64) {
44 		/*
45 		 * Handling 64 bit request or response
46 		 */
47 		msg->source_id = ffa_msg->source_id;
48 		msg->destination_id = ffa_msg->destination_id;
49 		msg->is_64bit_message = true;
50 
51 		memcpy(msg->args.args64, ffa_msg->args.args64, sizeof(msg->args.args64));
52 	} else {
53 		/* Success has no message parameters */
54 		*msg = (struct sp_msg){ 0 };
55 	}
56 }
57 
sp_msg_wait(struct sp_msg * msg)58 sp_result sp_msg_wait(struct sp_msg *msg)
59 {
60 	ffa_result ffa_res = FFA_OK;
61 	struct ffa_direct_msg ffa_msg = { 0 };
62 
63 	if (!msg)
64 		return SP_RESULT_INVALID_PARAMETERS;
65 
66 	ffa_res = ffa_msg_wait(&ffa_msg);
67 	if (ffa_res != FFA_OK) {
68 		*msg = (struct sp_msg){ 0 };
69 		return SP_RESULT_FFA(ffa_res);
70 	}
71 
72 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
73 	ffa_res = ffa_direct_msg_routing_ext_wait_post_hook(&ffa_msg);
74 	if (ffa_res != FFA_OK) {
75 		*msg = (struct sp_msg){ 0 };
76 		return SP_RESULT_FFA(ffa_res);
77 	}
78 #endif
79 
80 	unpack_ffa_direct_msg(&ffa_msg, msg);
81 
82 	return SP_RESULT_OK;
83 }
84 
sp_msg_send_direct_req(const struct sp_msg * req,struct sp_msg * resp)85 sp_result sp_msg_send_direct_req(const struct sp_msg *req, struct sp_msg *resp)
86 {
87 	ffa_result ffa_res = FFA_OK;
88 	struct ffa_direct_msg ffa_req = { 0 };
89 	struct ffa_direct_msg ffa_resp = { 0 };
90 
91 	if (!resp)
92 		return SP_RESULT_INVALID_PARAMETERS;
93 
94 	if (!req) {
95 		*resp = (struct sp_msg){ 0 };
96 		return SP_RESULT_INVALID_PARAMETERS;
97 	}
98 
99 	pack_ffa_direct_msg(req, &ffa_req);
100 
101 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
102 	ffa_res = ffa_direct_msg_routing_ext_req_pre_hook(&ffa_req);
103 	if (ffa_res != FFA_OK) {
104 		*resp = (struct sp_msg){ 0 };
105 		return SP_RESULT_INVALID_PARAMETERS;
106 	}
107 #endif
108 
109 	if (req->is_64bit_message)
110 		ffa_res = ffa_msg_send_direct_req_64(
111 			ffa_req.source_id, ffa_req.destination_id,
112 			ffa_req.args.args64[0], ffa_req.args.args64[1],
113 			ffa_req.args.args64[2], ffa_req.args.args64[3],
114 			ffa_req.args.args64[4], &ffa_resp);
115 	else
116 		ffa_res = ffa_msg_send_direct_req_32(
117 			ffa_req.source_id, ffa_req.destination_id,
118 			ffa_req.args.args32[0], ffa_req.args.args32[1],
119 			ffa_req.args.args32[2], ffa_req.args.args32[3],
120 			ffa_req.args.args32[4], &ffa_resp);
121 
122 	if (ffa_res != FFA_OK) {
123 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
124 		ffa_direct_msg_routing_ext_req_error_hook();
125 #endif
126 		*resp = (struct sp_msg){ 0 };
127 		return SP_RESULT_FFA(ffa_res);
128 	}
129 
130 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
131 	ffa_res = ffa_direct_msg_routing_ext_req_post_hook(&ffa_resp);
132 	if (ffa_res != SP_RESULT_OK) {
133 		*resp = (struct sp_msg){ 0 };
134 		return SP_RESULT_FFA(ffa_res);
135 	}
136 #endif
137 
138 	unpack_ffa_direct_msg(&ffa_resp, resp);
139 
140 	return SP_RESULT_OK;
141 }
142 
sp_msg_send_direct_resp(const struct sp_msg * resp,struct sp_msg * req)143 sp_result sp_msg_send_direct_resp(const struct sp_msg *resp, struct sp_msg *req)
144 {
145 	ffa_result ffa_res = FFA_OK;
146 	struct ffa_direct_msg ffa_resp = { 0 };
147 	struct ffa_direct_msg ffa_req = { 0 };
148 
149 	if (!req)
150 		return SP_RESULT_INVALID_PARAMETERS;
151 
152 	if (!resp) {
153 		*req = (struct sp_msg){ 0 };
154 		return SP_RESULT_INVALID_PARAMETERS;
155 	}
156 
157 	pack_ffa_direct_msg(resp, &ffa_resp);
158 
159 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
160 	ffa_res = ffa_direct_msg_routing_ext_resp_pre_hook(&ffa_resp);
161 	if (ffa_res != FFA_OK) {
162 		*req = (struct sp_msg){ 0 };
163 		return SP_RESULT_INVALID_PARAMETERS;
164 	}
165 #endif
166 
167 	if (resp->is_64bit_message)
168 		ffa_res = ffa_msg_send_direct_resp_64(
169 			ffa_resp.source_id, ffa_resp.destination_id,
170 			ffa_resp.args.args64[0], ffa_resp.args.args64[1],
171 			ffa_resp.args.args64[2], ffa_resp.args.args64[3],
172 			ffa_resp.args.args64[4], &ffa_req);
173 	else
174 		ffa_res = ffa_msg_send_direct_resp_32(
175 			ffa_resp.source_id, ffa_resp.destination_id,
176 			ffa_resp.args.args32[0], ffa_resp.args.args32[1],
177 			ffa_resp.args.args32[2], ffa_resp.args.args32[3],
178 			ffa_resp.args.args32[4], &ffa_req);
179 
180 	if (ffa_res != FFA_OK) {
181 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
182 		ffa_direct_msg_routing_ext_resp_error_hook();
183 #endif
184 		*req = (struct sp_msg){ 0 };
185 		return SP_RESULT_FFA(ffa_res);
186 	}
187 
188 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
189 	ffa_res = ffa_direct_msg_routing_ext_resp_post_hook(&ffa_req);
190 	if (ffa_res != SP_RESULT_OK) {
191 		*req = (struct sp_msg){ 0 };
192 		return SP_RESULT_FFA(ffa_res);
193 	}
194 #endif
195 
196 	unpack_ffa_direct_msg(&ffa_req, req);
197 
198 	return SP_RESULT_OK;
199 }
200 
201 #if FFA_DIRECT_MSG_ROUTING_EXTENSION
sp_msg_send_rc_req(const struct sp_msg * req,struct sp_msg * resp)202 sp_result sp_msg_send_rc_req(const struct sp_msg *req, struct sp_msg *resp)
203 {
204 	ffa_result ffa_res = FFA_OK;
205 	struct ffa_direct_msg ffa_req = { 0 };
206 	struct ffa_direct_msg ffa_resp = { 0 };
207 
208 	if (!resp)
209 		return SP_RESULT_INVALID_PARAMETERS;
210 
211 	if (!req) {
212 		*resp = (struct sp_msg){ 0 };
213 		return SP_RESULT_INVALID_PARAMETERS;
214 	}
215 
216 	pack_ffa_direct_msg(req, &ffa_req);
217 
218 	ffa_res = ffa_direct_msg_routing_ext_rc_req_pre_hook(&ffa_req);
219 	if (ffa_res != FFA_OK) {
220 		*resp = (struct sp_msg){ 0 };
221 		return SP_RESULT_INVALID_PARAMETERS;
222 	}
223 
224 	ffa_res = ffa_msg_send_direct_resp_32(ffa_req.source_id,
225 					   ffa_req.destination_id,
226 					   ffa_req.args.args32[0], ffa_req.args.args32[1],
227 					   ffa_req.args.args32[2], ffa_req.args.args32[3],
228 					   ffa_req.args.args32[4], &ffa_resp);
229 
230 	if (ffa_res != FFA_OK) {
231 		ffa_direct_msg_routing_ext_rc_req_error_hook();
232 		*resp = (struct sp_msg){ 0 };
233 		return SP_RESULT_FFA(ffa_res);
234 	}
235 
236 	ffa_res = ffa_direct_msg_routing_ext_rc_req_post_hook(&ffa_resp);
237 	if (ffa_res != SP_RESULT_OK) {
238 		*resp = (struct sp_msg){ 0 };
239 		return SP_RESULT_FFA(ffa_res);
240 	}
241 
242 	unpack_ffa_direct_msg(&ffa_resp, resp);
243 
244 	return SP_RESULT_OK;
245 }
246 #endif
247