Add fwu_provider
Adds the fwu_provider that implements the public service interface
for the FWU service.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I515998401086681e218c90e9a4a54606e3177ce2
diff --git a/components/service/fwu/provider/serializer/fwu_provider_serializer.h b/components/service/fwu/provider/serializer/fwu_provider_serializer.h
new file mode 100644
index 0000000..3c61bfd
--- /dev/null
+++ b/components/service/fwu/provider/serializer/fwu_provider_serializer.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FWU_PROVIDER_SERIALIZER_H
+#define FWU_PROVIDER_SERIALIZER_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <common/uuid/uuid.h>
+#include <rpc/common/endpoint/rpc_interface.h>
+
+/* Provides a common interface for parameter serialization operations
+ * for the fwu service provider. Allows alternative serialization
+ * protocols to be used without hard-wiring a particular protocol
+ * into the service provider code. A concrete serializer must
+ * implement this interface.
+ */
+struct fwu_provider_serializer {
+
+ /* Operation: open */
+ rpc_status_t (*deserialize_open_req)(
+ const struct call_param_buf *req_buf,
+ struct uuid_octets *image_type_uuid);
+
+ rpc_status_t (*serialize_open_resp)(
+ struct call_param_buf *resp_buf,
+ uint32_t handle);
+
+ /* Operation: write_stream */
+ rpc_status_t (*deserialize_write_stream_req)(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle,
+ size_t *data_len,
+ const uint8_t **data);
+
+ /* Operation: read_stream */
+ rpc_status_t (*deserialize_read_stream_req)(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle);
+
+ void (*read_stream_resp_payload)(
+ const struct call_param_buf *resp_buf,
+ uint8_t **payload_buf,
+ size_t *max_payload);
+
+ rpc_status_t (*serialize_read_stream_resp)(
+ struct call_param_buf *resp_buf,
+ size_t read_bytes,
+ size_t total_bytes);
+
+ /* Operation: commit */
+ rpc_status_t (*deserialize_commit_req)(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle,
+ bool *accepted,
+ size_t *max_atomic_len);
+
+ rpc_status_t (*serialize_commit_resp)(
+ struct call_param_buf *resp_buf,
+ size_t progress,
+ size_t total_work);
+
+ /* Operation: accept_image */
+ rpc_status_t (*deserialize_accept_req)(
+ const struct call_param_buf *req_buf,
+ struct uuid_octets *image_type_uuid);
+};
+
+#endif /* FWU_PROVIDER_SERIALIZER_H */
diff --git a/components/service/fwu/provider/serializer/packed-c/component.cmake b/components/service/fwu/provider/serializer/packed-c/component.cmake
new file mode 100644
index 0000000..4209cae
--- /dev/null
+++ b/components/service/fwu/provider/serializer/packed-c/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/packedc_fwu_provider_serializer.c"
+ )
diff --git a/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.c b/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.c
new file mode 100644
index 0000000..9413417
--- /dev/null
+++ b/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/fwu/packed-c/fwu_proto.h>
+#include "packedc_fwu_provider_serializer.h"
+
+
+static rpc_status_t deserialize_open_req(
+ const struct call_param_buf *req_buf,
+ struct uuid_octets *image_type_uuid)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ size_t expected_fixed_len = sizeof(struct ts_fwu_open_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ const struct ts_fwu_open_in *recv_msg =
+ (const struct ts_fwu_open_in *)req_buf->data;
+
+ memcpy(image_type_uuid->octets,
+ recv_msg->image_type_uuid, UUID_OCTETS_LEN);
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_open_resp(
+ struct call_param_buf *resp_buf,
+ uint32_t handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ size_t fixed_len = sizeof(struct ts_fwu_open_out);
+
+ if (fixed_len <= resp_buf->size) {
+
+ struct ts_fwu_open_out *resp_msg =
+ (struct ts_fwu_open_out *)resp_buf->data;
+
+ resp_msg->handle = handle;
+
+ resp_buf->data_len = fixed_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: write_stream */
+static rpc_status_t deserialize_write_stream_req(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle,
+ size_t *data_len,
+ const uint8_t **data)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ size_t expected_fixed_len = sizeof(struct ts_fwu_write_stream_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ const struct ts_fwu_write_stream_in *recv_msg =
+ (const struct ts_fwu_write_stream_in *)req_buf->data;
+
+ *handle = recv_msg->handle;
+ *data_len = recv_msg->data_len;
+ *data = recv_msg->payload;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: read_stream */
+static rpc_status_t deserialize_read_stream_req(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ size_t expected_fixed_len = sizeof(struct ts_fwu_read_stream_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ const struct ts_fwu_read_stream_in *recv_msg =
+ (const struct ts_fwu_read_stream_in *)req_buf->data;
+
+ *handle = recv_msg->handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static void read_stream_resp_payload(
+ const struct call_param_buf *resp_buf,
+ uint8_t **payload_buf,
+ size_t *max_payload)
+{
+ struct ts_fwu_read_stream_out *resp_msg = (struct ts_fwu_read_stream_out *)resp_buf->data;
+ size_t fixed_len = offsetof(struct ts_fwu_read_stream_out, payload);
+
+ *max_payload = 0;
+ *payload_buf = resp_msg->payload;
+
+ if (fixed_len < resp_buf->size)
+ *max_payload = resp_buf->size - fixed_len;
+}
+
+static rpc_status_t serialize_read_stream_resp(
+ struct call_param_buf *resp_buf,
+ size_t read_bytes,
+ size_t total_bytes)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ struct ts_fwu_read_stream_out *resp_msg = (struct ts_fwu_read_stream_out *)resp_buf->data;
+ size_t proto_overhead = offsetof(struct ts_fwu_read_stream_out, payload);
+
+ if (read_bytes > (SIZE_MAX - proto_overhead))
+ return TS_RPC_ERROR_INVALID_PARAMETER;
+
+ size_t required_len = proto_overhead + read_bytes;
+
+ if (required_len <= resp_buf->size) {
+
+ resp_msg->read_bytes = read_bytes;
+ resp_msg->total_bytes = total_bytes;
+
+ resp_buf->data_len = required_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: commit */
+static rpc_status_t deserialize_commit_req(
+ const struct call_param_buf *req_buf,
+ uint32_t *handle,
+ bool *accepted,
+ size_t *max_atomic_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ size_t expected_fixed_len = sizeof(struct ts_fwu_commit_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ const struct ts_fwu_commit_in *recv_msg =
+ (const struct ts_fwu_commit_in *)req_buf->data;
+
+ *handle = recv_msg->handle;
+ *accepted = (recv_msg->acceptance_req == 0);
+ *max_atomic_len = recv_msg->max_atomic_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_commit_resp(
+ struct call_param_buf *resp_buf,
+ size_t progress,
+ size_t total_work)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ struct ts_fwu_commit_out *resp_msg = (struct ts_fwu_commit_out *)resp_buf->data;
+
+ size_t required_len = sizeof(struct ts_fwu_commit_out);
+
+ if (required_len <= resp_buf->size) {
+
+ resp_msg->progress = progress;
+ resp_msg->total_work = total_work;
+
+ resp_buf->data_len = required_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: accept_image */
+static rpc_status_t deserialize_accept_req(
+ const struct call_param_buf *req_buf,
+ struct uuid_octets *image_type_uuid)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ size_t expected_fixed_len = sizeof(struct ts_fwu_accept_image_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ const struct ts_fwu_accept_image_in *recv_msg =
+ (const struct ts_fwu_accept_image_in *)req_buf->data;
+
+ memcpy(image_type_uuid->octets, recv_msg->image_type_uuid, UUID_OCTETS_LEN);
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Singleton method to provide access to the serializer instance */
+const struct fwu_provider_serializer *packedc_fwu_provider_serializer_instance(void)
+{
+ static const struct fwu_provider_serializer instance = {
+ deserialize_open_req,
+ serialize_open_resp,
+ deserialize_write_stream_req,
+ deserialize_read_stream_req,
+ read_stream_resp_payload,
+ serialize_read_stream_resp,
+ deserialize_commit_req,
+ serialize_commit_resp,
+ deserialize_accept_req
+ };
+
+ return &instance;
+}
diff --git a/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.h b/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.h
new file mode 100644
index 0000000..b9ced37
--- /dev/null
+++ b/components/service/fwu/provider/serializer/packed-c/packedc_fwu_provider_serializer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PACKEDC_FWU_PROVIDER_SERIALIZER_H
+#define PACKEDC_FWU_PROVIDER_SERIALIZER_H
+
+#include <service/fwu/provider/serializer/fwu_provider_serializer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Singleton method to provide access to the packed-c serializer
+ * for the fwu service provider.
+ */
+const struct fwu_provider_serializer *packedc_fwu_provider_serializer_instance(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PACKEDC_FWU_PROVIDER_SERIALIZER_H */