blob: 6d67870ffa73accec66ec3ba393f4869fcdd8de8 [file] [log] [blame]
/*
* Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fwu_provider_shim.h"
#include "protocols/service/fwu/fwu_proto.h"
#include "util.h"
static rpc_status_t receive(void *context, struct rpc_request *req)
{
struct rpc_service_interface *fwu_rpc_interface = (struct rpc_service_interface *)context;
struct fwu_request_header *req_header = NULL;
struct fwu_response_header *resp_header = NULL;
rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
struct rpc_request fwu_req = { 0 };
if (req->request.data_length < sizeof(*req_header))
return RPC_ERROR_INVALID_REQUEST_BODY;
if (req->response.size < sizeof(*resp_header))
return RPC_ERROR_INVALID_RESPONSE_BODY;
req_header = (struct fwu_request_header *)req->request.data;
resp_header = (struct fwu_response_header *)req->response.data;
/* Build new RPC request without the request headers */
fwu_req = *req;
fwu_req.opcode = req_header->func_id & 0xffff;
fwu_req.request.data = req_header->payload;
fwu_req.request.data_length -= sizeof(*req_header);
fwu_req.request.size -= sizeof(*req_header);
fwu_req.response.data = resp_header->payload;
fwu_req.response.size -= sizeof(*resp_header);
rpc_status = rpc_service_receive(fwu_rpc_interface, &fwu_req);
if (rpc_status != RPC_SUCCESS)
return rpc_status;
/* Insert service status into response buffer */
resp_header->status = fwu_req.service_status;
req->service_status = fwu_req.service_status;
/* Update response data length */
if (ADD_OVERFLOW(fwu_req.response.data_length, sizeof(uint32_t),
&req->response.data_length))
return RPC_ERROR_INVALID_RESPONSE_BODY;
if (req->response.data_length > req->response.size)
return RPC_ERROR_INVALID_RESPONSE_BODY;
return rpc_status;
}
struct rpc_service_interface *
fwu_provider_shim_init(struct fwu_provider_shim *shim,
struct rpc_service_interface *fwu_rpc_interface)
{
shim->shim_rpc_interface.receive = receive;
shim->shim_rpc_interface.context = fwu_rpc_interface;
shim->shim_rpc_interface.uuid = fwu_rpc_interface->uuid;
return &shim->shim_rpc_interface;
}
void fwu_provider_shim_deinit(struct fwu_provider_shim *shim)
{
(void)shim;
}