Test: Add IPC test service
This is the first version for IPC secure function test service:
- Only psa_wait_any(), psa_get(), psa_read(), psa_write() and
psa_end() are used now.
- Only support "block" mode for psa_wait_any()
Note:
- Remaining PSA functions TBD
- "Poll" mode for psa_wait_any() TBD
Change-Id: I882716075b9c92839d41372df355c364d24d7574
Signed-off-by: Edison Ai <edison.ai@arm.com>
diff --git a/test/test_services/CMakeLists.inc b/test/test_services/CMakeLists.inc
index 42c309c..85eda32 100644
--- a/test/test_services/CMakeLists.inc
+++ b/test/test_services/CMakeLists.inc
@@ -62,6 +62,13 @@
list(APPEND ALL_SRC_C_NS "${CORE_TEST_DIR}/tfm_secure_client_service/tfm_secure_client_service_api.c")
endif()
+if (NOT DEFINED CORE_TEST_IPC)
+ message(FATAL_ERROR "Incomplete build configuration: CORE_TEST_IPC is undefined. ")
+elseif (CORE_TEST_IPC)
+ list(APPEND ALL_SRC_C_S "${CORE_TEST_DIR}/tfm_ipc_test/ipc_test_service.c"
+ )
+endif()
+
embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
diff --git a/test/test_services/tfm_ipc_test/ipc_test_service.c b/test/test_services/tfm_ipc_test/ipc_test_service.c
new file mode 100644
index 0000000..ab1a1f1
--- /dev/null
+++ b/test/test_services/tfm_ipc_test/ipc_test_service.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "psa_client.h"
+#include "psa_service.h"
+#include "secure_fw/core/tfm_thread.h"
+#include "secure_fw/core/secure_utilities.h"
+#include "secure_fw/core/tfm_secure_api.h"
+#include "tfm_api.h"
+
+#define IPC_SERVICE_BUFFER_LEN 256
+#define PSA_IPC_SIGNAL 1
+
+static int inuse = 0;
+
+static int ipc_service_connect(psa_msg_t *msg)
+{
+ uint32_t minor_version;
+
+ if (msg->in_size[0] == 0) {
+ return PSA_CONNECTION_REFUSED;
+ }
+
+ psa_read(msg->handle, 0, &minor_version, sizeof(minor_version));
+ printf("Requested minor version for service1 connect: %d.\r\n",
+ minor_version);
+
+ /* notify client if accepted or refused */
+ if (minor_version == 0) {
+ return PSA_CONNECTION_REFUSED;
+ }
+ return PSA_CONNECTION_ACCEPTED;
+}
+
+static psa_error_t ipc_service_call(psa_msg_t *msg)
+{
+ int i;
+ uint8_t rec_buf[IPC_SERVICE_BUFFER_LEN];
+ uint8_t send_buf[IPC_SERVICE_BUFFER_LEN] = "It is just for IPC call test.";
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ if (msg->in_size[i] != 0) {
+ psa_read(msg->handle, i, rec_buf, IPC_SERVICE_BUFFER_LEN);
+ printf("receive buffer index is %d, data is %s.\r\n", i,
+ (char *)rec_buf);
+ }
+ if (msg->out_size[i] != 0) {
+ psa_write(msg->handle, i, send_buf, IPC_SERVICE_BUFFER_LEN);
+ }
+ }
+ return PSA_SUCCESS;
+}
+
+/* Test thread */
+static void *ipc_test_partition_main(void *param)
+{
+ uint32_t signals = 0;
+ psa_msg_t msg;
+ int r;
+
+ while (1) {
+ signals = psa_wait_any(PSA_BLOCK);
+
+ printf("ipc get signals 0x%x\r\n", signals);
+
+ if (signals & PSA_IPC_SIGNAL) {
+ psa_get(PSA_IPC_SIGNAL, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ if (inuse) {
+ r = PSA_CONNECTION_REFUSED;
+ } else {
+ inuse = 1;
+ r = ipc_service_connect(&msg);
+ }
+ psa_end(msg.handle, r);
+ break;
+ case PSA_IPC_CALL:
+ psa_end(msg.handle, ipc_service_call(&msg));
+ break;
+ case PSA_IPC_DISCONNECT:
+ assert (inuse == 1);
+ inuse = 0;
+ psa_end(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ /* cannot get here? [broken SPM]. TODO*/
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+REGISTER_TFM_THREAD(ipc_test_partition_main, (void *)0x1, 1024);