From 7953806fd3fdb743c40b76e363b917fac786c636 Mon Sep 17 00:00:00 2001
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Date: Tue, 11 Mar 2025 13:33:36 +0000
Subject: [PATCH 10/11] platform: corstone1000: Add event provider proxy

Normal world needs to send boot confirmation event
to Secure Enclave and Trusted-Services is responsible
to transfer the event to Secure Enclave.
This commit implements the event handling framework in
SE-proxy-SP and develops event provider proxy which
forwards the event to Secure Enclave via psa calls.
This change is introduced for Corstone-1000

Upstream-Status: Pending
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
---
 components/service/common/include/psa/sid.h   |  9 ++
 .../se-proxy/env/commonsp/se_proxy_sp.c       | 16 +++-
 .../corstone1000_event_handling.c             | 91 +++++++++++++++++++
 .../corstone1000_event_handling.h             | 42 +++++++++
 .../se-proxy/infra/corstone1000/infra.cmake   |  1 +
 .../corstone1000/service_proxy_factory.c      | 27 ++++++
 6 files changed, 184 insertions(+), 2 deletions(-)
 create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c
 create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h

diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
index 0235764d..9f5ea05e 100644
--- a/components/service/common/include/psa/sid.h
+++ b/components/service/common/include/psa/sid.h
@@ -40,6 +40,15 @@ extern "C" {
 #define TFM_CRYPTO_VERSION                                         (1U)
 #define TFM_CRYPTO_HANDLE                                          (0x40000100U)
 
+/******** TFM_PLATFORM_SERVICE *******/
+#define TFM_PLATFORM_API_ID_IOCTL         (1013)
+#define TFM_PLATFORM_SERVICE_HANDLE       (0x40000105U)
+
+/**
+ * \brief Define a progressive numerical value for each SID which can be used
+ *        when dispatching the requests to the service
+*/
+
 /******** TFM_SP_PLATFORM ********/
 #define TFM_SP_PLATFORM_SYSTEM_RESET_SID                           (0x00000040U)
 #define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION                       (1U)
diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c
index 9f94092b..ce1410b2 100644
--- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c
+++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  */
 
 #include "components/rpc/common/endpoint/rpc_service_interface.h"
@@ -42,7 +42,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info)
 		goto fatal_error;
 	}
 
-	rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 6, 16);
+	rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 7, 16);
 	if (rpc_status != RPC_SUCCESS) {
 		EMSG("Failed to initialize RPC endpoint: %d", rpc_status);
 		goto fatal_error;
@@ -97,6 +97,18 @@ void __noreturn sp_main(union ffa_boot_info *boot_info)
 		goto fatal_error;
 	}
 
+	rpc_iface = event_handler_proxy_create();
+	if (!rpc_iface) {
+		EMSG("Failed to create Capsule Update proxy");
+		goto fatal_error;
+	}
+
+	rpc_status = ts_rpc_endpoint_sp_add_service(&rpc_endpoint, rpc_iface);
+	if (rpc_status != RPC_SUCCESS) {
+		EMSG("Failed to add service to RPC endpoint: %d", rpc_status);
+		goto fatal_error;
+	}
+
 	rpc_iface = fwu_proxy_create();
 	if (!rpc_iface) {
 		EMSG("Failed to create FWU proxy");
diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c
new file mode 100644
index 00000000..faf450f2
--- /dev/null
+++ b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <psa/client.h>
+#include <psa/sid.h>
+#include <trace.h>
+
+#include <protocols/rpc/common/packed-c/status.h>
+#include "corstone1000_event_handling.h"
+
+#define BOOT_CONFIRMED_EVENT   (0x3)
+#define OPCODE_BOOT_CONFIRMED  BOOT_CONFIRMED_EVENT
+
+enum corstone1000_ioctl_id {
+	IOCTL_CORSTONE1000_FWU_HOST_ACK = 1,
+};
+
+/* Service request handlers */
+static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req);
+
+/* Handler mapping table for service */
+static const struct service_handler handler_table[] = {
+	{OPCODE_BOOT_CONFIRMED,			boot_confirmed_handler}
+};
+
+struct rpc_service_interface *corstone1000_event_provider_init(
+	struct event_provider *context)
+{
+	struct rpc_service_interface *rpc_interface = NULL;
+	const struct rpc_uuid dummy_uuid = { .uuid = { 0 }};
+	if (!context)
+		return NULL;
+
+	service_provider_init(
+		&context->base_provider,
+		context,
+		&dummy_uuid,
+		handler_table,
+		sizeof(handler_table)/sizeof(struct service_handler));
+
+	rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
+
+	return rpc_interface;
+}
+
+static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface *caller)
+{
+	uint32_t ioctl_id;
+	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
+
+	struct psa_invec in_vec[] = {
+			{ .base = &ioctl_id, .len = sizeof(ioctl_id) }
+	};
+
+	if(!caller) {
+		EMSG("event_handler rpc_caller is NULL");
+		rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		return rpc_status;
+	}
+
+	IMSG("event handler opcode %x", opcode);
+	switch(opcode) {
+		case OPCODE_BOOT_CONFIRMED:
+		ioctl_id = IOCTL_CORSTONE1000_FWU_HOST_ACK;
+		/* Boot Confirmed event from Normal World  */
+		
+		psa_call(caller,TFM_PLATFORM_SERVICE_HANDLE, TFM_PLATFORM_API_ID_IOCTL,
+			in_vec,IOVEC_LEN(in_vec), NULL, 0);
+		break;
+		default:
+			EMSG("%s unsupported opcode", __func__);
+			rpc_status = TS_RPC_ERROR_INVALID_PARAMETER;
+	}
+	return rpc_status;
+
+}
+
+static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req)
+{
+	struct event_provider *this_instance = (struct event_provider*)context;
+	struct rpc_caller_interface *caller = this_instance->client.session->caller;
+	uint32_t opcode = req->opcode;
+	rpc_status_t rpc_status;
+
+	rpc_status = event_handler(opcode, caller);
+
+	return rpc_status;
+}
diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h
new file mode 100644
index 00000000..e8e60dae
--- /dev/null
+++ b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORSTONE1000_EVENT_HANDLING_H
+#define CORSTONE1000_EVENT_HANDLING_H
+
+#include <rpc/common/endpoint/rpc_service_interface.h>
+#include <service/common/provider/service_provider.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The event_provider is a service provider that accepts events
+ * and delegates them to a suitable backend.
+ */
+struct event_provider
+{
+	struct service_provider base_provider;
+	struct service_client client;
+};
+
+/**
+ * \brief Initialize an instance of the event handler
+ *
+ * @param[in] context The instance to initialize
+ *
+ * \return An rpc_service_interface or NULL on failure
+ */
+struct rpc_service_interface *corstone1000_event_provider_init(
+	struct event_provider *context);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CORSTONE1000_EVENT_HANDLING_H */
diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake
index 2bf6b36e..1ec43700 100644
--- a/deployments/se-proxy/infra/corstone1000/infra.cmake
+++ b/deployments/se-proxy/infra/corstone1000/infra.cmake
@@ -33,4 +33,5 @@ add_components(TARGET "se-proxy"
 target_sources(se-proxy PRIVATE
 
 	${CMAKE_CURRENT_LIST_DIR}/service_proxy_factory.c
+	${CMAKE_CURRENT_LIST_DIR}/corstone1000_event_handling.c
 )
diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
index a754ace7..6d8c3855 100644
--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
+++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
@@ -20,6 +20,7 @@
 #include <protocols/service/fwu/fwu_proto.h>
 #include <trace.h>
 #include "corstone1000_config.h"
+#include "corstone1000_event_handling.h"
 
 /* backends */
 #include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
@@ -164,6 +165,32 @@ struct rpc_service_interface *its_proxy_create(void)
 	return secure_storage_provider_init(&its_provider, backend, &its_uuid);
 }
 
+struct rpc_service_interface *event_handler_proxy_create(void)
+{
+	static struct event_provider event_provider = {0};
+	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
+
+	/* Static objects for proxy instance */
+	static struct rpc_caller_interface rse_comms = { 0 };
+	static struct rpc_caller_session rpc_session = { 0 };
+
+	rpc_status = rse_comms_caller_init(&rse_comms);
+	if (rpc_status != RPC_SUCCESS)
+		return NULL;
+
+	rpc_status = rpc_caller_session_open(&rpc_session, &rse_comms, &dummy_uuid, 0, 0);
+	if (rpc_status != RPC_SUCCESS)
+		return NULL;
+
+
+	event_provider.client.session = &rpc_session;
+	event_provider.client.rpc_status = RPC_SUCCESS;
+	event_provider.client.service_info.supported_encodings = 0;
+	event_provider.client.service_info.max_payload = 4096;
+
+	return corstone1000_event_provider_init(&event_provider);
+}
+
 struct rpc_service_interface *fwu_proxy_create(void)
 {
 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
-- 
2.34.1

