Implement RPMB provider
Implement RPMB service provider to make remote RPMB backends accessible
via the RPC layer.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: Id8d04a8cb12fb1d118e653022107207217a9800a
diff --git a/components/service/rpmb/provider/component.cmake b/components/service/rpmb/provider/component.cmake
new file mode 100644
index 0000000..a616667
--- /dev/null
+++ b/components/service/rpmb/provider/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, 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}/rpmb_provider.c"
+)
diff --git a/components/service/rpmb/provider/rpmb_provider.c b/components/service/rpmb/provider/rpmb_provider.c
new file mode 100644
index 0000000..847eec1
--- /dev/null
+++ b/components/service/rpmb/provider/rpmb_provider.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "rpmb_provider.h"
+#include "components/service/rpmb/backend/rpmb_backend.h"
+#include "protocols/service/rpmb/packed-c/rpmb_proto.h"
+#include "util.h"
+#include <string.h>
+
+static rpc_status_t get_dev_info_handler(void *context, struct rpc_request *req)
+{
+ struct rpmb_provider *this_context = (struct rpmb_provider *)context;
+ struct rpmb_request_get_dev_info *request_desc = NULL;
+ struct rpmb_response_get_dev_info *response_desc = NULL;
+
+ if (req->request.data_length < sizeof(*request_desc))
+ return RPC_ERROR_INVALID_REQUEST_BODY;
+
+ if (req->response.size < sizeof(*response_desc))
+ return RPC_ERROR_INVALID_RESPONSE_BODY;
+
+ request_desc = (struct rpmb_request_get_dev_info *)(req->request.data);
+ response_desc = (struct rpmb_response_get_dev_info *)(req->response.data);
+
+ req->service_status = rpmb_backend_get_dev_info(this_context->backend, request_desc->dev_id,
+ &response_desc->dev_info);
+
+ if (!req->service_status)
+ req->response.data_length = sizeof(*response_desc);
+
+ return RPC_SUCCESS;
+}
+
+static bool validate_size(size_t header_size, uint32_t frame_count, size_t available_length,
+ size_t *total_size)
+{
+ /*
+ * Checking if [data frame count] * [data frame size] + [header size] fits into the RPC
+ * buffer.
+ */
+
+ if (MUL_OVERFLOW(frame_count, sizeof(struct rpmb_data_frame), total_size))
+ return false;
+
+ if (ADD_OVERFLOW(*total_size, header_size, total_size))
+ return false;
+
+ if (*total_size > available_length)
+ return false;
+
+ return true;
+}
+
+static rpc_status_t data_request_handler(void *context, struct rpc_request *req)
+{
+ struct rpmb_provider *this_context = (struct rpmb_provider *)context;
+ struct rpmb_request_data_request *request_desc = NULL;
+ struct rpmb_response_data_request *response_desc = NULL;
+ size_t response_frame_count = 0;
+ size_t total_size = 0;
+
+ if (req->request.data_length < sizeof(*request_desc))
+ return RPC_ERROR_INVALID_REQUEST_BODY;
+
+ request_desc = (struct rpmb_request_data_request *)(req->request.data);
+
+ if (!validate_size(sizeof(*request_desc), request_desc->request_frame_count,
+ req->request.data_length, &total_size))
+ return RPC_ERROR_INVALID_REQUEST_BODY;
+
+ if (!validate_size(sizeof(*response_desc), request_desc->max_response_frame_count,
+ req->response.size, &total_size))
+ return RPC_ERROR_INVALID_RESPONSE_BODY;
+
+ response_desc = (struct rpmb_response_data_request *)(req->response.data);
+ response_frame_count = request_desc->max_response_frame_count;
+
+ req->service_status = rpmb_backend_data_request(
+ this_context->backend,
+ request_desc->dev_id,
+ request_desc->request_frames,
+ request_desc->request_frame_count,
+ response_desc->response_frames,
+ &response_frame_count);
+
+ if (!req->service_status) {
+ if (!validate_size(sizeof(*response_desc), response_frame_count,
+ req->response.size, &total_size))
+ return RPC_ERROR_INVALID_RESPONSE_BODY;
+
+ response_desc->response_frame_count = response_frame_count;
+ req->response.data_length = total_size;
+ }
+
+ return RPC_SUCCESS;
+}
+
+static const struct service_handler handler_table[] = {
+ {TS_RPMB_OPCODE_GET_DEV_INFO, get_dev_info_handler},
+ {TS_RPMB_OPCODE_DATA_REQUEST, data_request_handler},
+};
+
+struct rpc_service_interface *rpmb_provider_init(struct rpmb_provider *context,
+ struct rpmb_backend *backend,
+ const struct rpc_uuid *service_uuid)
+{
+ struct rpc_service_interface *rpc_interface = NULL;
+
+ if (!context || !backend || !service_uuid)
+ return NULL;
+
+ service_provider_init(&context->base_provider, context, service_uuid, handler_table,
+ ARRAY_SIZE(handler_table));
+
+ rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
+
+ context->backend = backend;
+
+ return rpc_interface;
+}
+
+void rpmb_provider_deinit(struct rpmb_provider *context)
+{
+ (void)context;
+}
diff --git a/components/service/rpmb/provider/rpmb_provider.h b/components/service/rpmb/provider/rpmb_provider.h
new file mode 100644
index 0000000..59366e4
--- /dev/null
+++ b/components/service/rpmb/provider/rpmb_provider.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPMB_PROVIDER_H_
+#define RPMB_PROVIDER_H_
+
+#include "service/common/provider/service_provider.h"
+#include "service/rpmb/backend/rpmb_backend.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief RPMB service provider
+ */
+struct rpmb_provider {
+ struct service_provider base_provider;
+ struct rpmb_backend *backend;
+};
+
+/**
+ * \brief Initializes the RPMB service provider
+ *
+ * \param context[in] Provider context
+ * \param backend[in] RPMB backend
+ * \param service_uuid[in] Service UUID
+ * \return struct rpc_service_interface* RPC service interface or NULL on error
+ */
+struct rpc_service_interface *rpmb_provider_init(struct rpmb_provider *context,
+ struct rpmb_backend *backend,
+ const struct rpc_uuid *service_uuid);
+
+/**
+ * \brief Deinitializes the RPMB service provider
+ *
+ * \param context[in] Provider context
+ */
+void rpmb_provider_deinit(struct rpmb_provider *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPMB_PROVIDER_H_ */
diff --git a/components/service/rpmb/provider/rpmb_uuid.h b/components/service/rpmb/provider/rpmb_uuid.h
new file mode 100644
index 0000000..63ea4f5
--- /dev/null
+++ b/components/service/rpmb/provider/rpmb_uuid.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPMB_UUID_H
+#define RPMB_UUID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TS_RPMB_SERVICE_UUID \
+{ 0x19, 0xef, 0x70, 0xbf, 0x2f, 0xbc, 0x43, 0x09, 0xbd, 0xd3, 0xc2, 0x90, 0xe9, 0x93, 0xf6, 0x50 }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPMB_UUID_H */