| // SPDX-License-Identifier: BSD-3-Clause |
| /* |
| * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. |
| */ |
| |
| #include "ffa_api.h" |
| #include "sp_api_defines.h" |
| #include "sp_messaging.h" |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| #include "ffa_direct_msg_routing_extension.h" |
| #endif |
| |
| #include <string.h> |
| |
| static void pack_ffa_direct_msg(const struct sp_msg *msg, |
| struct ffa_direct_msg *ffa_msg) |
| { |
| ffa_msg->source_id = msg->source_id; |
| ffa_msg->destination_id = msg->destination_id; |
| |
| if (msg->is_64bit_message) { |
| ffa_msg->function_id = FFA_TO_64_BIT_FUNC(0); |
| memcpy(ffa_msg->args.args64, msg->args.args64, sizeof(msg->args.args64)); |
| } else { |
| memcpy(ffa_msg->args.args32, msg->args.args32, sizeof(msg->args.args32)); |
| } |
| } |
| |
| static void unpack_ffa_direct_msg(const struct ffa_direct_msg *ffa_msg, |
| struct sp_msg *msg) |
| { |
| if (ffa_msg->function_id == FFA_MSG_SEND_DIRECT_REQ_32 || |
| ffa_msg->function_id == FFA_MSG_SEND_DIRECT_RESP_32) { |
| /* |
| * Handling 32 bit request or response |
| */ |
| msg->source_id = ffa_msg->source_id; |
| msg->destination_id = ffa_msg->destination_id; |
| msg->is_64bit_message = false; |
| |
| memcpy(msg->args.args32, ffa_msg->args.args32, sizeof(msg->args.args32)); |
| } else if (ffa_msg->function_id == FFA_MSG_SEND_DIRECT_REQ_64 || |
| ffa_msg->function_id == FFA_MSG_SEND_DIRECT_RESP_64) { |
| /* |
| * Handling 64 bit request or response |
| */ |
| msg->source_id = ffa_msg->source_id; |
| msg->destination_id = ffa_msg->destination_id; |
| msg->is_64bit_message = true; |
| |
| memcpy(msg->args.args64, ffa_msg->args.args64, sizeof(msg->args.args64)); |
| } else { |
| /* Success has no message parameters */ |
| *msg = (struct sp_msg){ 0 }; |
| } |
| } |
| |
| sp_result sp_msg_wait(struct sp_msg *msg) |
| { |
| ffa_result ffa_res = FFA_OK; |
| struct ffa_direct_msg ffa_msg = { 0 }; |
| |
| if (!msg) |
| return SP_RESULT_INVALID_PARAMETERS; |
| |
| ffa_res = ffa_msg_wait(&ffa_msg); |
| if (ffa_res != FFA_OK) { |
| *msg = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_res = ffa_direct_msg_routing_ext_wait_post_hook(&ffa_msg); |
| if (ffa_res != FFA_OK) { |
| *msg = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| #endif |
| |
| unpack_ffa_direct_msg(&ffa_msg, msg); |
| |
| return SP_RESULT_OK; |
| } |
| |
| sp_result sp_msg_send_direct_req(const struct sp_msg *req, struct sp_msg *resp) |
| { |
| ffa_result ffa_res = FFA_OK; |
| struct ffa_direct_msg ffa_req = { 0 }; |
| struct ffa_direct_msg ffa_resp = { 0 }; |
| |
| if (!resp) |
| return SP_RESULT_INVALID_PARAMETERS; |
| |
| if (!req) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| |
| pack_ffa_direct_msg(req, &ffa_req); |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_res = ffa_direct_msg_routing_ext_req_pre_hook(&ffa_req); |
| if (ffa_res != FFA_OK) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| #endif |
| |
| if (req->is_64bit_message) |
| ffa_res = ffa_msg_send_direct_req_64( |
| ffa_req.source_id, ffa_req.destination_id, |
| ffa_req.args.args64[0], ffa_req.args.args64[1], |
| ffa_req.args.args64[2], ffa_req.args.args64[3], |
| ffa_req.args.args64[4], &ffa_resp); |
| else |
| ffa_res = ffa_msg_send_direct_req_32( |
| ffa_req.source_id, ffa_req.destination_id, |
| ffa_req.args.args32[0], ffa_req.args.args32[1], |
| ffa_req.args.args32[2], ffa_req.args.args32[3], |
| ffa_req.args.args32[4], &ffa_resp); |
| |
| if (ffa_res != FFA_OK) { |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_direct_msg_routing_ext_req_error_hook(); |
| #endif |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_res = ffa_direct_msg_routing_ext_req_post_hook(&ffa_resp); |
| if (ffa_res != SP_RESULT_OK) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| #endif |
| |
| unpack_ffa_direct_msg(&ffa_resp, resp); |
| |
| return SP_RESULT_OK; |
| } |
| |
| sp_result sp_msg_send_direct_resp(const struct sp_msg *resp, struct sp_msg *req) |
| { |
| ffa_result ffa_res = FFA_OK; |
| struct ffa_direct_msg ffa_resp = { 0 }; |
| struct ffa_direct_msg ffa_req = { 0 }; |
| |
| if (!req) |
| return SP_RESULT_INVALID_PARAMETERS; |
| |
| if (!resp) { |
| *req = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| |
| pack_ffa_direct_msg(resp, &ffa_resp); |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_res = ffa_direct_msg_routing_ext_resp_pre_hook(&ffa_resp); |
| if (ffa_res != FFA_OK) { |
| *req = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| #endif |
| |
| if (resp->is_64bit_message) |
| ffa_res = ffa_msg_send_direct_resp_64( |
| ffa_resp.source_id, ffa_resp.destination_id, |
| ffa_resp.args.args64[0], ffa_resp.args.args64[1], |
| ffa_resp.args.args64[2], ffa_resp.args.args64[3], |
| ffa_resp.args.args64[4], &ffa_req); |
| else |
| ffa_res = ffa_msg_send_direct_resp_32( |
| ffa_resp.source_id, ffa_resp.destination_id, |
| ffa_resp.args.args32[0], ffa_resp.args.args32[1], |
| ffa_resp.args.args32[2], ffa_resp.args.args32[3], |
| ffa_resp.args.args32[4], &ffa_req); |
| |
| if (ffa_res != FFA_OK) { |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_direct_msg_routing_ext_resp_error_hook(); |
| #endif |
| *req = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| ffa_res = ffa_direct_msg_routing_ext_resp_post_hook(&ffa_req); |
| if (ffa_res != SP_RESULT_OK) { |
| *req = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| #endif |
| |
| unpack_ffa_direct_msg(&ffa_req, req); |
| |
| return SP_RESULT_OK; |
| } |
| |
| #if FFA_DIRECT_MSG_ROUTING_EXTENSION |
| sp_result sp_msg_send_rc_req(const struct sp_msg *req, struct sp_msg *resp) |
| { |
| ffa_result ffa_res = FFA_OK; |
| struct ffa_direct_msg ffa_req = { 0 }; |
| struct ffa_direct_msg ffa_resp = { 0 }; |
| |
| if (!resp) |
| return SP_RESULT_INVALID_PARAMETERS; |
| |
| if (!req) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| |
| pack_ffa_direct_msg(req, &ffa_req); |
| |
| ffa_res = ffa_direct_msg_routing_ext_rc_req_pre_hook(&ffa_req); |
| if (ffa_res != FFA_OK) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_INVALID_PARAMETERS; |
| } |
| |
| ffa_res = ffa_msg_send_direct_resp_32(ffa_req.source_id, |
| ffa_req.destination_id, |
| ffa_req.args.args32[0], ffa_req.args.args32[1], |
| ffa_req.args.args32[2], ffa_req.args.args32[3], |
| ffa_req.args.args32[4], &ffa_resp); |
| |
| if (ffa_res != FFA_OK) { |
| ffa_direct_msg_routing_ext_rc_req_error_hook(); |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| |
| ffa_res = ffa_direct_msg_routing_ext_rc_req_post_hook(&ffa_resp); |
| if (ffa_res != SP_RESULT_OK) { |
| *resp = (struct sp_msg){ 0 }; |
| return SP_RESULT_FFA(ffa_res); |
| } |
| |
| unpack_ffa_direct_msg(&ffa_resp, resp); |
| |
| return SP_RESULT_OK; |
| } |
| #endif |