Transmit FWU function ID and status fields in shared memory
The PSA firmware update protocol transmits the function ID and status
fields in the request/response structures in the shared memory. Add shim
layer to extract and insert common function ID and status fields. This
way the actual FWU provider functions don't have to individually handle
these fields.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: Icdf73caf2f56da39bf1c384b4fafbe8fe9885555
diff --git a/components/service/fwu/provider/fwu_provider_shim.c b/components/service/fwu/provider/fwu_provider_shim.c
new file mode 100644
index 0000000..0f1e471
--- /dev/null
+++ b/components/service/fwu/provider/fwu_provider_shim.c
@@ -0,0 +1,72 @@
+/*
+ * 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/packed-c/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 ts_fwu_request_header *req_header = NULL;
+ struct ts_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 ts_fwu_request_header *)req->request.data;
+ resp_header = (struct ts_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;
+}