Add log provider component

Add component for handling logging RPC calls from SPs.

Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
Signed-off-by: Gabor Ambrus <gabor.ambrus@arm.com>
Change-Id: I6d09bac2c77eaff1356e2d8f0d0883aa7803b998
diff --git a/components/service/log/backend/log_backend.h b/components/service/log/backend/log_backend.h
new file mode 100644
index 0000000..2ac4c33
--- /dev/null
+++ b/components/service/log/backend/log_backend.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LOG_BACKEND_H
+#define LOG_BACKEND_H
+
+#include "components/service/log/common/log_status.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Common log backend interface
+ *
+ * A concrete log backend provides an implementation of this
+ * interface.
+ */
+struct log_backend_interface {
+	/**
+	* \brief Processes the character sequence (str) in a desired way (e.g. print to UART).
+	*
+	* \param[in]  context	The concrete backend context
+	* \param[in]  str	Character sequence to be printed (null-terminated)
+	*/
+	log_status_t (*puts)(void *context, const char *str);
+};
+
+/**
+ * \brief Common log backend instance
+ */
+struct log_backend {
+	/**
+	* \brief The backend context
+	*
+	* Points to backend specific instance data.
+	*/
+	void *context;
+
+	/**
+	* \brief The backend interface
+	*
+	* A concrete backend provides an implementation of this interface.
+	*/
+	const struct log_backend_interface *interface;
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LOG_BACKEND_H */
diff --git a/components/service/log/common/log_status.h b/components/service/log/common/log_status.h
new file mode 100644
index 0000000..1fca78e
--- /dev/null
+++ b/components/service/log/common/log_status.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LOG_STATUS_H
+#define LOG_STATUS_H
+
+#include <stdint.h>
+
+typedef int32_t log_status_t;
+
+#define LOG_STATUS_SUCCESS	     ((log_status_t)0)
+#define LOG_STATUS_GENERIC_ERROR     ((log_status_t)-1)
+#define LOG_STATUS_INVALID_PARAMETER ((log_status_t)-2)
+
+#endif /* LOG_STATUS_H */
diff --git a/components/service/log/provider/component.cmake b/components/service/log/provider/component.cmake
new file mode 100644
index 0000000..c5d043e
--- /dev/null
+++ b/components/service/log/provider/component.cmake
@@ -0,0 +1,19 @@
+#-------------------------------------------------------------------------------
+# 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}/log_provider.c"
+	)
+
+
+target_include_directories(${TGT}
+	 PRIVATE
+		"${CMAKE_CURRENT_LIST_DIR}"
+	)
diff --git a/components/service/log/provider/log_provider.c b/components/service/log/provider/log_provider.c
new file mode 100644
index 0000000..8d5e5f9
--- /dev/null
+++ b/components/service/log/provider/log_provider.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include "log_provider.h"
+
+#include "components/rpc/common/endpoint/rpc_service_interface.h"
+#include "components/service/log/common/log_status.h"
+#include "log_uuid.h"
+#include "protocols/rpc/common/packed-c/status.h"
+#include "protocols/service/log/packed-c/log_proto.h"
+#include "util.h"
+
+static rpc_status_t log_puts_handler(void *context, struct rpc_request *req);
+
+static const struct service_handler handler_table[] = { { TS_LOG_OPCODE_PUTS, log_puts_handler } };
+
+struct rpc_service_interface *log_provider_init(struct log_provider *context,
+						struct log_backend *backend)
+{
+	const struct rpc_uuid service_uuid = { .uuid = TS_LOG_SERVICE_UUID };
+
+	if (context == NULL || backend == NULL)
+		return NULL;
+
+	service_provider_init(&context->base_provider, context, &service_uuid, handler_table,
+			      ARRAY_SIZE(handler_table));
+
+	context->backend = backend;
+
+	return service_provider_get_rpc_interface(&context->base_provider);
+}
+
+/*
+ * Handler function for provider to call puts operation of the attached backend.
+ */
+static rpc_status_t log_puts_handler(void *context, struct rpc_request *req)
+{
+	struct log_provider *this_context = (struct log_provider *)context;
+	struct log_request *request_desc = NULL;
+	size_t request_data_length = 0;
+
+	/* Checking if the descriptor fits into the request buffer */
+	if (req->request.data_length < sizeof(struct log_request))
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	request_desc = (struct log_request *)(req->request.data);
+
+	/* Checking for overflow */
+	if (ADD_OVERFLOW(sizeof(*request_desc), request_desc->msg_length, &request_data_length))
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	/* Checking if descriptor and data fits into the request buffer */
+	if (req->request.data_length < request_data_length)
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	/* Make sure it is null terminated */
+	if (request_desc->msg_length != 0)
+		request_desc->msg[request_desc->msg_length - 1] = '\0';
+
+	this_context->backend->interface->puts(this_context->backend->context, request_desc->msg);
+	req->service_status = LOG_STATUS_SUCCESS;
+
+	return RPC_SUCCESS;
+}
diff --git a/components/service/log/provider/log_provider.h b/components/service/log/provider/log_provider.h
new file mode 100644
index 0000000..ec1c7f9
--- /dev/null
+++ b/components/service/log/provider/log_provider.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LOG_PROVIDER_H
+#define LOG_PROVIDER_H
+
+#include "components/service/common/provider/service_provider.h"
+#include "service/log/backend/log_backend.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct log_provider {
+	struct service_provider base_provider;
+	struct log_backend *backend;
+};
+
+struct rpc_service_interface *log_provider_init(struct log_provider *context,
+						struct log_backend *backend);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOG_PROVIDER_H */
diff --git a/components/service/log/provider/log_uuid.h b/components/service/log/provider/log_uuid.h
new file mode 100644
index 0000000..1d5d1d1
--- /dev/null
+++ b/components/service/log/provider/log_uuid.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LOG_UUID_H
+#define LOG_UUID_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define TS_LOG_SERVICE_UUID \
+{ 0xda, 0x9d, 0xff, 0xbd, 0xd5, 0x90, 0x40, 0xed, 0x97, 0x5f, 0x19, 0xc6, 0x5a, 0x3d, 0x52, 0xd3 }
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LOG_UUID_H */
\ No newline at end of file
diff --git a/protocols/service/log/packed-c/component.cmake b/protocols/service/log/packed-c/component.cmake
new file mode 100644
index 0000000..8fa3490
--- /dev/null
+++ b/protocols/service/log/packed-c/component.cmake
@@ -0,0 +1,16 @@
+#-------------------------------------------------------------------------------
+# 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_include_directories(${TGT}
+	PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}"
+	)
diff --git a/protocols/service/log/packed-c/log_proto.h b/protocols/service/log/packed-c/log_proto.h
new file mode 100644
index 0000000..54f6420
--- /dev/null
+++ b/protocols/service/log/packed-c/log_proto.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LOG_PROTO_H
+#define LOG_PROTO_H
+
+#include <stdint.h>
+
+struct __attribute__ ((__packed__)) log_request {
+	uint64_t msg_length;
+	char msg[];
+};
+
+/* Opcodes */
+#define TS_LOG_OPCODE_BASE (0x0100)
+#define TS_LOG_OPCODE_PUTS (TS_LOG_OPCODE_BASE + 1)
+
+#endif /* LOG_PROTO_H */