Add common service component to ipc support

Add support for inter processor communication for PSA
including, the openamp client side structures lib, and
a rpc caller interface.

Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Change-Id: I889fdc627989a95d726535f4c6820744392ed881
diff --git a/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.c b/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.c
new file mode 100644
index 0000000..bc5dfe7
--- /dev/null
+++ b/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "psa_ipc_caller.h"
+#include <openamp_messenger_api.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <rpc_caller.h>
+#include <rpc_status.h>
+#include <trace.h>
+#include <errno.h>
+#include <stdint.h>
+
+static rpc_call_handle psa_ipc_call_begin(void *context, uint8_t **req_buf,
+					  size_t req_len)
+{
+	struct psa_ipc_caller *psa_ipc = context;
+	struct openamp_messenger *openamp = &psa_ipc->openamp;
+	rpc_call_handle handle;
+	int ret;
+
+	ret = openamp_messenger_call_begin(openamp, req_buf, req_len);
+	if (ret < 0)
+		return NULL;
+
+	handle = psa_ipc;
+
+	return handle;
+}
+
+static rpc_status_t psa_ipc_call_invoke(void *context, rpc_call_handle handle,
+					uint32_t opcode, long int *opstatus,
+					uint8_t **resp_buf, size_t *resp_len)
+{
+	struct psa_ipc_caller *psa_ipc = context;
+	struct openamp_messenger *openamp = &psa_ipc->openamp;
+	int ret;
+
+	(void)opcode;
+
+	ret = openamp_messenger_call_invoke(openamp, resp_buf, resp_len);
+	if (ret == -EINVAL)
+		return TS_RPC_ERROR_INVALID_PARAMETER;
+	if (ret == -ENOTCONN)
+		return TS_RPC_ERROR_NOT_READY;
+	if (ret < 0)
+		return TS_RPC_ERROR_INTERNAL;
+
+	*opstatus = 0;
+
+	return TS_RPC_CALL_ACCEPTED;
+}
+
+static void psa_ipc_call_end(void *context, rpc_call_handle handle)
+{
+	struct psa_ipc_caller *psa_ipc = context;
+
+	if (!psa_ipc || psa_ipc != handle) {
+		EMSG("psa_ipc: call_end: invalid arguments");
+		return;
+	}
+
+	openamp_messenger_call_end(&psa_ipc->openamp);
+}
+
+
+void *psa_ipc_phys_to_virt(void *context, void *pa)
+{
+	struct psa_ipc_caller *psa_ipc = context;
+	struct openamp_messenger *openamp = &psa_ipc->openamp;
+
+	return openamp_messenger_phys_to_virt(openamp, pa);
+}
+
+void *psa_ipc_virt_to_phys(void *context, void *va)
+{
+	struct psa_ipc_caller *psa_ipc = context;
+	struct openamp_messenger *openamp = &psa_ipc->openamp;
+
+	return openamp_messenger_virt_to_phys(openamp, va);
+}
+
+struct rpc_caller *psa_ipc_caller_init(struct psa_ipc_caller *psa_ipc)
+{
+	struct rpc_caller *rpc = &psa_ipc->rpc_caller;
+	int ret;
+
+	ret = openamp_messenger_init(&psa_ipc->openamp);
+	if (ret < 0)
+		return NULL;
+
+	rpc_caller_init(rpc, &psa_ipc->rpc_caller);
+	rpc->call_begin = psa_ipc_call_begin;
+	rpc->call_invoke = psa_ipc_call_invoke;
+	rpc->call_end = psa_ipc_call_end;
+
+	return rpc;
+}
+
+struct rpc_caller *psa_ipc_caller_deinit(struct psa_ipc_caller *psa_ipc)
+{
+	struct rpc_caller *rpc = &psa_ipc->rpc_caller;
+
+	rpc->context = NULL;
+	rpc->call_begin = NULL;
+	rpc->call_invoke = NULL;
+	rpc->call_end = NULL;
+
+	return rpc;
+}
diff --git a/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.h b/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.h
new file mode 100644
index 0000000..1b84e98
--- /dev/null
+++ b/components/rpc/psa_ipc/caller/sp/psa_ipc_caller.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <rpc_caller.h>
+#include <openamp_messenger_api.h>
+
+struct psa_ipc_caller {
+	struct rpc_caller rpc_caller;
+	struct openamp_messenger openamp;
+};
+
+void *psa_ipc_phys_to_virt(void *context, void *pa);
+void *psa_ipc_virt_to_phys(void *context, void *va);
+
+struct rpc_caller *psa_ipc_caller_init(struct psa_ipc_caller *psaipc);
+struct rpc_caller *psa_ipc_caller_deinit(struct psa_ipc_caller *psaipc);
diff --git a/components/rpc/psa_ipc/component.cmake b/components/rpc/psa_ipc/component.cmake
new file mode 100644
index 0000000..5d9c72b
--- /dev/null
+++ b/components/rpc/psa_ipc/component.cmake
@@ -0,0 +1,24 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-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()
+
+set_property(TARGET ${TGT} APPEND PROPERTY PUBLIC_HEADER
+	${CMAKE_CURRENT_LIST_DIR}/caller/sp/psa_ipc_caller.h
+	)
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/service_psa_ipc.c"
+	"${CMAKE_CURRENT_LIST_DIR}/caller/sp/psa_ipc_caller.c"
+	)
+
+target_include_directories(${TGT}
+	 PUBLIC
+		"${CMAKE_CURRENT_LIST_DIR}/caller/sp/"
+	)
+
diff --git a/components/rpc/psa_ipc/service_psa_ipc.c b/components/rpc/psa_ipc/service_psa_ipc.c
new file mode 100644
index 0000000..830f461
--- /dev/null
+++ b/components/rpc/psa_ipc/service_psa_ipc.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <trace.h>
+
+#include <protocols/rpc/common/packed-c/status.h>
+#include <psa/error.h>
+#include <rpc_caller.h>
+
+#include <psa/client.h>
+#include <psa_ipc_caller.h>
+#include "service_psa_ipc_openamp_lib.h"
+
+static inline void *unaligned_memcpy(void *dst_init, const void *src_init,
+				     size_t len)
+{
+	char *dst = dst_init;
+	const char *src = src_init;
+
+	while (len--)
+		*dst++ = *src++;
+
+	return dst_init;
+}
+
+static struct psa_invec *psa_call_in_vec_param(uint8_t *req)
+{
+	return (struct psa_invec *)(req + sizeof(struct ns_openamp_msg));
+}
+
+static struct psa_outvec *psa_call_out_vec_param(uint8_t *req, size_t in_len)
+{
+	return (struct psa_outvec *)(req + sizeof(struct ns_openamp_msg) +
+				     (in_len * sizeof(struct psa_invec)));
+}
+
+static size_t psa_call_header_len(const struct psa_invec *in_vec, size_t in_len,
+				  struct psa_outvec *out_vec, size_t out_len)
+{
+	return sizeof(struct ns_openamp_msg) + (in_len * sizeof(*in_vec)) +
+		(out_len * sizeof(*out_vec));
+}
+
+static size_t psa_call_in_vec_len(const struct psa_invec *in_vec, size_t in_len)
+{
+	size_t req_len = 0;
+	int i;
+
+	if (!in_vec || !in_len)
+		return 0;
+
+	for (i = 0; i < in_len; i++)
+		req_len += in_vec[i].len;
+
+	return req_len;
+}
+
+static uint32_t psa_virt_to_phys_u32(struct rpc_caller *caller, void *va)
+{
+	return (uintptr_t)psa_ipc_virt_to_phys(caller->context, va);
+}
+
+psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
+			 uint32_t version)
+{
+	rpc_opstatus_t opstatus = PSA_SUCCESS;
+	struct s_openamp_msg *resp_msg = NULL;
+	struct ns_openamp_msg *req_msg;
+	rpc_call_handle rpc_handle;
+	size_t resp_len;
+	uint8_t *resp;
+	uint8_t *req;
+	int ret;
+
+	rpc_handle = rpc_caller_begin(caller, &req,
+				      sizeof(struct ns_openamp_msg));
+	if (!rpc_handle) {
+		EMSG("psa_connect: could not get rpc handle");
+		return PSA_ERROR_GENERIC_ERROR;
+	}
+
+	req_msg = (struct ns_openamp_msg *)req;
+
+	req_msg->call_type = OPENAMP_PSA_CONNECT;
+	req_msg->params.psa_connect_params.sid = sid;
+	req_msg->params.psa_connect_params.version = version;
+
+	ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
+				&resp_len);
+	if (ret != TS_RPC_CALL_ACCEPTED) {
+		EMSG("psa_connect: invoke failed: %d", ret);
+		return PSA_ERROR_GENERIC_ERROR;
+	}
+
+	if (opstatus == PSA_SUCCESS)
+		resp_msg = (struct s_openamp_msg *)resp;
+
+	rpc_caller_end(caller, rpc_handle);
+
+	return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
+}
+
+static psa_status_t __psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+			       int32_t client_id, int32_t type,
+			       const struct psa_invec *in_vec, size_t in_len,
+			       struct psa_outvec *out_vec, size_t out_len)
+{
+	rpc_opstatus_t opstatus = PSA_SUCCESS;
+	struct s_openamp_msg *resp_msg = NULL;
+	struct psa_outvec *out_vec_param;
+	struct psa_invec *in_vec_param;
+	struct ns_openamp_msg *req_msg;
+	rpc_call_handle rpc_handle;
+	size_t in_vec_len;
+	size_t header_len;
+	uint8_t *payload;
+	size_t resp_len;
+	uint8_t *resp;
+	uint8_t *req;
+	int ret;
+	int i;
+
+	if ((psa_handle == PSA_NULL_HANDLE) || !caller)
+		return PSA_ERROR_INVALID_ARGUMENT;
+
+	header_len = psa_call_header_len(in_vec, in_len, out_vec, out_len);
+	in_vec_len = psa_call_in_vec_len(in_vec, in_len);
+
+	rpc_handle = rpc_caller_begin(caller, &req, header_len + in_vec_len);
+	if (!rpc_handle) {
+		EMSG("psa_call: could not get handle");
+		return PSA_ERROR_GENERIC_ERROR;
+	}
+
+	payload = req + header_len;
+
+	out_vec_param = psa_call_out_vec_param(req, in_len);
+	in_vec_param = psa_call_in_vec_param(req);
+
+	req_msg = (struct ns_openamp_msg *)req;
+
+	req_msg->call_type = OPENAMP_PSA_CALL;
+	req_msg->request_id = 1234;
+	req_msg->client_id = client_id;
+	req_msg->params.psa_call_params.handle = psa_handle;
+	req_msg->params.psa_call_params.type = type;
+	req_msg->params.psa_call_params.in_len = in_len;
+	req_msg->params.psa_call_params.in_vec = psa_virt_to_phys_u32(caller, in_vec_param);
+	req_msg->params.psa_call_params.out_len = out_len;
+	req_msg->params.psa_call_params.out_vec = psa_virt_to_phys_u32(caller, out_vec_param);
+
+	for (i = 0; i < in_len; i++) {
+		in_vec_param[i].base = psa_virt_to_phys_u32(caller, payload);
+		in_vec_param[i].len = in_vec[i].len;
+
+		unaligned_memcpy(payload, psa_u32_to_ptr(in_vec[i].base),
+				 in_vec[i].len);
+		payload += in_vec[i].len;
+	}
+
+	for (i = 0; i < out_len; i++) {
+		out_vec_param[i].base = 0;
+		out_vec_param[i].len = out_vec[i].len;
+	}
+
+	ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
+				&resp_len);
+	if (ret != TS_RPC_CALL_ACCEPTED) {
+		EMSG("psa_call: invoke failed: %d", ret);
+		return PSA_ERROR_GENERIC_ERROR;
+	}
+
+	if (opstatus != PSA_SUCCESS) {
+		EMSG("psa_call: psa_status invoke failed: %ld", opstatus);
+		return PSA_ERROR_GENERIC_ERROR;
+	}
+
+	resp_msg = (struct s_openamp_msg *)resp;
+
+	if (!resp_msg || !out_len || resp_msg->reply != PSA_SUCCESS)
+		goto caller_end;
+
+	out_vec_param = (struct psa_outvec *)psa_ipc_phys_to_virt(caller,
+				psa_u32_to_ptr(resp_msg->params.out_vec));
+
+	for (i = 0; i < resp_msg->params.out_len; i++) {
+		out_vec[i].len = out_vec_param[i].len;
+		unaligned_memcpy(psa_u32_to_ptr(out_vec[i].base),
+				 psa_ipc_phys_to_virt(caller,
+				      psa_u32_to_ptr(out_vec_param[i].base)),
+				 out_vec[i].len);
+	}
+
+caller_end:
+	rpc_caller_end(caller, rpc_handle);
+
+	return resp_msg ? resp_msg->reply : PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_call_client_id(struct rpc_caller *caller,
+				psa_handle_t psa_handle, int32_t client_id,
+				int32_t type, const struct psa_invec *in_vec,
+				size_t in_len, struct psa_outvec *out_vec,
+				size_t out_len)
+{
+	return __psa_call(caller, psa_handle, client_id, type, in_vec, in_len,
+			  out_vec, out_len);
+}
+
+psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+		      int32_t type, const struct psa_invec *in_vec,
+		      size_t in_len, struct psa_outvec *out_vec, size_t out_len)
+{
+	return __psa_call(caller, psa_handle, 0, type, in_vec, in_len, out_vec,
+			  out_len);
+}
+
+void psa_close(struct rpc_caller *caller, psa_handle_t psa_handle)
+{
+	rpc_opstatus_t opstatus = PSA_SUCCESS;
+	struct ns_openamp_msg *req_msg;
+	rpc_call_handle rpc_handle;
+	size_t resp_len;
+	uint8_t *resp;
+	uint8_t *req;
+	int ret;
+
+	if ((psa_handle == PSA_NULL_HANDLE) || !caller)
+		return;
+
+	rpc_handle = rpc_caller_begin(caller, &req,
+				      sizeof(struct ns_openamp_msg));
+	if (!rpc_handle) {
+		EMSG("psa_close: could not get handle");
+		return;
+	}
+
+	req_msg = (struct ns_openamp_msg *)req;
+
+	req_msg->call_type = OPENAMP_PSA_CLOSE;
+	req_msg->params.psa_close_params.handle = psa_handle;
+
+	ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
+				&resp_len);
+	if (ret != TS_RPC_CALL_ACCEPTED) {
+		EMSG("psa_close: invoke failed: %d", ret);
+		return;
+	}
+
+	rpc_caller_end(caller, rpc_handle);
+}
diff --git a/components/rpc/psa_ipc/service_psa_ipc_openamp_lib.h b/components/rpc/psa_ipc/service_psa_ipc_openamp_lib.h
new file mode 100644
index 0000000..38ad2ed
--- /dev/null
+++ b/components/rpc/psa_ipc/service_psa_ipc_openamp_lib.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SERVICE_PSA_IPC_OPENAMP_LIB_H
+#define SERVICE_PSA_IPC_OPENAMP_LIB_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <compiler.h>
+#include <psa/error.h>
+
+#include <stdint.h>
+#include <psa/client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* PSA client call type value */
+#define OPENAMP_PSA_FRAMEWORK_VERSION       (0x1)
+#define OPENAMP_PSA_VERSION                 (0x2)
+#define OPENAMP_PSA_CONNECT                 (0x3)
+#define OPENAMP_PSA_CALL                    (0x4)
+#define OPENAMP_PSA_CLOSE                   (0x5)
+
+/* Return code of openamp APIs */
+#define OPENAMP_SUCCESS                     (0)
+#define OPENAMP_MAP_FULL                    (INT32_MIN + 1)
+#define OPENAMP_MAP_ERROR                   (INT32_MIN + 2)
+#define OPENAMP_INVAL_PARAMS                (INT32_MIN + 3)
+#define OPENAMP_NO_PERMS                    (INT32_MIN + 4)
+#define OPENAMP_NO_PEND_EVENT               (INT32_MIN + 5)
+#define OPENAMP_CHAN_BUSY                   (INT32_MIN + 6)
+#define OPENAMP_CALLBACK_REG_ERROR          (INT32_MIN + 7)
+#define OPENAMP_INIT_ERROR                  (INT32_MIN + 8)
+
+#define HOLD_INPUT_BUFFER (1) /* IF true, TF-M Library will hold the openamp
+			       * buffer so that openamp shared memory buffer
+			       * does not get freed.
+			       */
+
+/*
+ * This structure holds the parameters used in a PSA client call.
+ */
+typedef struct __packed psa_client_in_params {
+	union {
+		struct __packed {
+			uint32_t        sid;
+		} psa_version_params;
+
+		struct __packed {
+			uint32_t        sid;
+			uint32_t        version;
+		} psa_connect_params;
+
+		struct __packed {
+			psa_handle_t     handle;
+			int32_t          type;
+			uint32_t         in_vec;
+			uint32_t         in_len;
+			uint32_t         out_vec;
+			uint32_t         out_len;
+		} psa_call_params;
+
+		struct __packed {
+			psa_handle_t    handle;
+		} psa_close_params;
+	};
+} psa_client_in_params_t;
+
+/* Openamp message passed from NSPE to SPE to deliver a PSA client call */
+struct __packed ns_openamp_msg {
+	uint32_t                      call_type;   /* PSA client call type */
+	struct psa_client_in_params   params;      /* Contain parameters used in PSA
+						  * client call
+						  */
+
+	int32_t                     client_id;   /* Optional client ID of the
+						  * non-secure caller.
+						  * It is required to identify the
+						  * non-secure task when NSPE OS
+						  * enforces non-secure task
+						  * isolation
+						  */
+	int32_t                     request_id;  /* This is the unique ID for a
+						  * request send to TF-M by the
+						  * non-secure core. TF-M forward
+						  * the ID back to non-secure on the
+						  * reply to a given request. Using
+						  * this id, the non-secure library
+						  * can identify the request for
+						  * which the reply has received.
+						  */
+};
+
+/*
+ * This structure holds the location of the out data of the PSA client call.
+ */
+struct __packed psa_client_out_params {
+	uint32_t              out_vec;
+	uint32_t              out_len;
+};
+
+
+/* Openamp message from SPE to NSPE delivering the reply back for a PSA client
+ * call.
+ */
+struct __packed s_openamp_msg {
+	int32_t                     request_id;  /* Using this id, the non-secure
+						  * library identifies the request.
+						  * TF-M forwards the same
+						  * request-id received on the
+						  * initial request.
+						  */
+	int32_t                     reply;       /* Reply of the PSA client call */
+	struct psa_client_out_params     params;      /* Contain out data result of the
+						       * PSA client call.
+						       */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SERVICE_PSA_IPC_OPENAMP_LIB_H */
+
+
diff --git a/components/service/common/include/psa/client.h b/components/service/common/include/psa/client.h
index fb253d7..2f39aa6 100644
--- a/components/service/common/include/psa/client.h
+++ b/components/service/common/include/psa/client.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -81,6 +81,21 @@
     uint32_t len;                 /*!< the size in bytes                      */
 };
 
+inline static void *psa_u32_to_ptr(uint32_t addr)
+{
+	return (void *)(uintptr_t)addr;
+}
+
+inline static uint32_t psa_ptr_to_u32(void *ptr)
+{
+	return (uintptr_t)ptr;
+}
+
+inline static uint32_t psa_ptr_const_to_u32(const void *ptr)
+{
+	return (uintptr_t)ptr;
+}
+
 /*************************** PSA Client API **********************************/
 
 /**
@@ -169,6 +184,45 @@
 		      size_t in_len, struct psa_outvec *out_vec, size_t out_len);
 
 /**
+ * \brief Call an RoT Service on an established connection.
+ *
+ * \note  FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI
+ *        support at most 4 parameters. TF-M chooses to encode 'in_len',
+ *        'out_len', and 'type' into a 32-bit integer to improve efficiency.
+ *        Compared with struct-based encoding, this method saves extra memory
+ *        check and memory copy operation. The disadvantage is that the 'type'
+ *        range has to be reduced into a 16-bit integer. So with this encoding,
+ *        the valid range for 'type' is 0-32767.
+ *
+ * \param[in] rpc_caller        RPC caller to use
+ * \param[in] handle            A handle to an established connection.
+ * \param[in] client_id         A client_id to be passed over the request
+ * \param[in] type              The request type.
+ *                              Must be zero( \ref PSA_IPC_CALL) or positive.
+ * \param[in] in_vec            Array of input \ref psa_invec structures.
+ * \param[in] in_len            Number of input \ref psa_invec structures.
+ * \param[in,out] out_vec       Array of output \ref psa_outvec structures.
+ * \param[in] out_len           Number of output \ref psa_outvec structures.
+ *
+ * \retval >=0                  RoT Service-specific status value.
+ * \retval <0                   RoT Service-specific error code.
+ * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
+ *                              RoT Service. The call is a PROGRAMMER ERROR if
+ *                              one or more of the following are true:
+ * \arg                           An invalid handle was passed.
+ * \arg                           The connection is already handling a request.
+ * \arg                           type < 0.
+ * \arg                           An invalid memory reference was provided.
+ * \arg                           in_len + out_len > PSA_MAX_IOVEC.
+ * \arg                           The message is unrecognized by the RoT
+ *                                Service or incorrectly formatted.
+ */
+psa_status_t psa_call_client_id(struct rpc_caller *caller, psa_handle_t handle,
+				int32_t client_id, int32_t type,
+				const struct psa_invec *in_vec, size_t in_len,
+				struct psa_outvec *out_vec, size_t out_len);
+
+/**
  * \brief Close a connection to an RoT Service.
  *
  * \param[in] rpc_caller        RPC caller to use
diff --git a/deployments/se-proxy/se-proxy.cmake b/deployments/se-proxy/se-proxy.cmake
index 426c66c..368f9b4 100644
--- a/deployments/se-proxy/se-proxy.cmake
+++ b/deployments/se-proxy/se-proxy.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #