Add TS RPC ABI component
Add definitions and setters/getters for accessing TS RPC protocol fields
of RPC messages transmitted over FF-A direct messages.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I354fee84f693d65382d92eed50634ba9ff69ed65
diff --git a/components/rpc/ts_rpc/common/component.cmake b/components/rpc/ts_rpc/common/component.cmake
new file mode 100644
index 0000000..71d4e8e
--- /dev/null
+++ b/components/rpc/ts_rpc/common/component.cmake
@@ -0,0 +1,18 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, 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}/ts_rpc_abi.h"
+ )
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/ts_rpc_abi.c"
+ )
diff --git a/components/rpc/ts_rpc/common/test/test_ts_rpc_abi.cpp b/components/rpc/ts_rpc/common/test/test_ts_rpc_abi.cpp
new file mode 100644
index 0000000..463792b
--- /dev/null
+++ b/components/rpc/ts_rpc/common/test/test_ts_rpc_abi.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../ts_rpc_abi.h"
+#include <stdint.h>
+#include <string.h>
+#include <CppUTest/TestHarness.h>
+
+TEST_GROUP(ts_rpc_abi) {
+ TEST_SETUP() {
+ memset(regs, 0x00, sizeof(regs));
+ }
+
+ void set_regs(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4)
+ {
+ regs[0] = a0;
+ regs[1] = a1;
+ regs[2] = a2;
+ regs[3] = a3;
+ regs[4] = a4;
+ }
+
+ void check_regs(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4)
+ {
+ UNSIGNED_LONGS_EQUAL(a0, regs[0]);
+ UNSIGNED_LONGS_EQUAL(a1, regs[1]);
+ UNSIGNED_LONGS_EQUAL(a2, regs[2]);
+ UNSIGNED_LONGS_EQUAL(a3, regs[3]);
+ UNSIGNED_LONGS_EQUAL(a4, regs[4]);
+ }
+
+ uint32_t regs[5];
+};
+
+TEST(ts_rpc_abi, flags)
+{
+ const uint8_t flags = 0x3f;
+
+ ts_rpc_abi_set_flags(regs, flags);
+ check_regs(0x3f000000, 0, 0, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(flags, ts_rpc_abi_get_flags(regs));
+}
+
+TEST(ts_rpc_abi, interface_id)
+{
+ const uint8_t interface_id = 0xa5;
+
+ ts_rpc_abi_set_interface_id(regs, interface_id);
+ check_regs(0x00a50000, 0, 0, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(interface_id, ts_rpc_abi_get_interface_id(regs));
+}
+
+TEST(ts_rpc_abi, management_interface_id)
+{
+ CHECK_FALSE(ts_rpc_abi_is_management_interface_id(regs));
+
+ ts_rpc_abi_set_management_interface_id(regs);
+ check_regs(0x00ff0000, 0, 0, 0, 0);
+
+ CHECK_TRUE(ts_rpc_abi_is_management_interface_id(regs));
+}
+
+TEST(ts_rpc_abi, opcode)
+{
+ const uint16_t opcode = 0x8765;
+
+ ts_rpc_abi_set_opcode(regs, 0x8765);
+ check_regs(0x00008765, 0, 0, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(0x8765, ts_rpc_abi_get_opcode(regs));
+}
+
+TEST(ts_rpc_abi, copy_control_reg)
+{
+ uint32_t source_regs[5] = { 0xfedcba98, 0, 0, 0, 0 };
+
+ ts_rpc_abi_copy_control_reg(regs, source_regs);
+
+ check_regs(0xfedcba98, 0, 0, 0, 0);
+}
+
+TEST(ts_rpc_abi, version)
+{
+ const uint32_t version = 0x98765432;
+
+ ts_rpc_abi_set_version(regs, version);
+ check_regs(0, version, 0, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(version, ts_rpc_abi_get_version(regs));
+
+}
+
+TEST(ts_rpc_abi, memory_handle)
+{
+ const uint64_t handle = 0xfedcba9876543210;
+
+ ts_rpc_abi_set_memory_handle(regs, handle);
+ check_regs(0, 0x76543210, 0xfedcba98, 0, 0);
+
+ UNSIGNED_LONGLONGS_EQUAL(handle, ts_rpc_abi_get_memory_handle(regs));
+}
+
+TEST(ts_rpc_abi, memory_tag)
+{
+ const uint64_t tag = 0xfedcba9876543210;
+
+ ts_rpc_abi_set_memory_tag(regs, tag);
+ check_regs(0, 0, 0, 0x76543210, 0xfedcba98);
+
+ UNSIGNED_LONGLONGS_EQUAL(tag, ts_rpc_abi_get_memory_tag(regs));
+}
+
+TEST(ts_rpc_abi, rpc_status)
+{
+ const uint32_t rpc_status = 0x89abcdef;
+
+ ts_rpc_abi_set_rpc_status(regs, rpc_status);
+ check_regs(0, rpc_status, 0, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(rpc_status, ts_rpc_abi_get_rpc_status(regs));
+}
+
+TEST(ts_rpc_abi, service_status)
+{
+ const uint32_t service_status = 0x89abcdef;
+
+ ts_rpc_abi_set_service_status(regs, service_status);
+ check_regs(0, 0, service_status, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(service_status, ts_rpc_abi_get_service_status(regs));
+}
+
+TEST(ts_rpc_abi, uuid)
+{
+ const struct rpc_uuid expected = {
+ .uuid = { 0xf0, 0x33, 0xbe, 0x6d, 0x6c, 0xc4, 0x47, 0x38,
+ 0x88, 0xfd, 0xdd, 0x44, 0xac, 0x56, 0x2b, 0x69}
+ };
+ struct rpc_uuid actual = { 0 };
+
+ ts_rpc_abi_set_uuid(regs, &expected);
+ check_regs(0, 0x6dbe33f0, 0x3847c46c, 0x44ddfd88, 0x692b56ac);
+
+ ts_rpc_abi_get_uuid(regs, &actual);
+ MEMCMP_EQUAL(expected.uuid, actual.uuid, sizeof(expected));
+}
+
+TEST(ts_rpc_abi, queried_interface_id)
+{
+ const uint8_t interface_id = 0xa5;
+
+ ts_rpc_abi_set_queried_interface_id(regs, interface_id);
+ check_regs(0, 0, interface_id, 0, 0);
+
+ UNSIGNED_LONGS_EQUAL(interface_id, ts_rpc_abi_get_queried_interface_id(regs));
+}
+
+TEST(ts_rpc_abi, request_length)
+{
+ const uint32_t length = 0x12345678;
+
+ ts_rpc_abi_set_request_length(regs, length);
+ check_regs(0, 0, 0, length, 0);
+
+ UNSIGNED_LONGS_EQUAL(length, ts_rpc_abi_get_request_length(regs));
+}
+
+TEST(ts_rpc_abi, client_id)
+{
+ const uint32_t client_id = 0xabcdef01;
+
+ ts_rpc_abi_set_client_id(regs, client_id);
+ check_regs(0, 0, 0, 0, client_id);
+
+ UNSIGNED_LONGS_EQUAL(client_id, ts_rpc_abi_get_client_id(regs));
+}
+
+TEST(ts_rpc_abi, response_length)
+{
+ const uint32_t length = 0x12345678;
+
+ ts_rpc_abi_set_response_length(regs, length);
+ check_regs(0, 0, 0, length, 0);
+
+ UNSIGNED_LONGS_EQUAL(length, ts_rpc_abi_get_response_length(regs));
+}
diff --git a/components/rpc/ts_rpc/common/ts_rpc_abi.c b/components/rpc/ts_rpc/common/ts_rpc_abi.c
new file mode 100644
index 0000000..674e668
--- /dev/null
+++ b/components/rpc/ts_rpc/common/ts_rpc_abi.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "ts_rpc_abi.h"
+#include <string.h>
+
+#define TS_RPC_CONTROL_REG (0)
+
+#define TS_RPC_FLAGS_REG (0)
+#define TS_RPC_FLAGS_SHIFT (24)
+#define TS_RPC_FLAGS_MASK (0x3f)
+
+#define TS_RPC_INTERFACE_ID_REG (0)
+#define TS_RPC_INTERFACE_ID_SHIFT (16)
+#define TS_RPC_INTERFACE_ID_MASK (0xff)
+
+#define TS_RPC_MANAGEMENT_INTERFACE_ID (0xff)
+
+#define TS_RPC_OPCODE_REG (0)
+#define TS_RPC_OPCODE_SHIFT (0)
+#define TS_RPC_OPCODE_MASK (0xffff)
+
+#define TS_RPC_VERSION_REG (1)
+#define TS_RPC_MEMORY_HANDLE_LSW_REG (1)
+#define TS_RPC_MEMORY_HANDLE_MSW_REG (2)
+#define TS_RPC_MEMORY_TAG_LSW_REG (3)
+#define TS_RPC_MEMORY_TAG_MSW_REG (4)
+#define TS_RPC_RPC_STATUS_REG (1)
+#define TS_RPC_SERVICE_STATUS_REG (2)
+#define TS_RPC_UUID_START_REG (1)
+
+#define TS_RPC_QUERIED_INTERFACE_ID_REG (2)
+#define TS_RPC_QUERIED_INTERFACE_ID_SHIFT (0)
+#define TS_RPC_QUERIED_INTERFACE_ID_MASK (0xff)
+
+#define TS_RPC_REQUEST_LENGTH_REG (3)
+#define TS_RPC_CLIENT_ID_REG (4)
+#define TS_RPC_RESPONSE_LENGTH_REG (3)
+#define TS_RPC_FAST_REQUEST_DATA_START_REG (1)
+#define TS_RPC_FAST_RESPONSE_DATA_START_REG (2)
+
+static uint32_t get_field(const uint32_t regs[5], uint32_t reg, uint32_t shift, uint32_t mask)
+{
+ return (regs[reg] >> shift) & mask;
+}
+
+static void set_field(uint32_t regs[5], uint32_t reg, uint32_t shift, uint32_t mask,
+ uint32_t value)
+{
+ regs[reg] &= ~(mask << shift);
+ regs[reg] |= (value & mask) << shift;
+}
+
+uint8_t ts_rpc_abi_get_flags(const uint32_t regs[5])
+{
+ return get_field(regs, TS_RPC_FLAGS_REG, TS_RPC_FLAGS_SHIFT, TS_RPC_FLAGS_MASK);
+}
+
+void ts_rpc_abi_set_flags(uint32_t regs[5], uint8_t flags)
+{
+ set_field(regs, TS_RPC_FLAGS_REG, TS_RPC_FLAGS_SHIFT, TS_RPC_FLAGS_MASK, flags);
+}
+
+uint8_t ts_rpc_abi_get_interface_id(const uint32_t regs[5])
+{
+ return get_field(regs, TS_RPC_INTERFACE_ID_REG, TS_RPC_INTERFACE_ID_SHIFT,
+ TS_RPC_INTERFACE_ID_MASK);
+}
+
+void ts_rpc_abi_set_interface_id(uint32_t regs[5], uint8_t interface_id)
+{
+ set_field(regs, TS_RPC_INTERFACE_ID_REG, TS_RPC_INTERFACE_ID_SHIFT,
+ TS_RPC_INTERFACE_ID_MASK, interface_id);
+}
+
+bool ts_rpc_abi_is_management_interface_id(const uint32_t regs[5])
+{
+ return ts_rpc_abi_get_interface_id(regs) == TS_RPC_MANAGEMENT_INTERFACE_ID;
+}
+
+void ts_rpc_abi_set_management_interface_id(uint32_t regs[5])
+{
+ ts_rpc_abi_set_interface_id(regs, TS_RPC_MANAGEMENT_INTERFACE_ID);
+}
+
+uint16_t ts_rpc_abi_get_opcode(const uint32_t regs[5])
+{
+ return get_field(regs, TS_RPC_OPCODE_REG, TS_RPC_OPCODE_SHIFT, TS_RPC_OPCODE_MASK);
+}
+
+void ts_rpc_abi_set_opcode(uint32_t regs[5], uint16_t opcode)
+{
+ set_field(regs, TS_RPC_OPCODE_REG, TS_RPC_OPCODE_SHIFT, TS_RPC_OPCODE_MASK, opcode);
+}
+
+void ts_rpc_abi_copy_control_reg(uint32_t response_regs[5], const uint32_t request_regs[5])
+{
+ response_regs[TS_RPC_CONTROL_REG] = request_regs[TS_RPC_CONTROL_REG];
+}
+
+uint32_t ts_rpc_abi_get_version(const uint32_t regs[5])
+{
+ return regs[TS_RPC_VERSION_REG];
+}
+
+void ts_rpc_abi_set_version(uint32_t regs[5], uint32_t version)
+{
+ regs[TS_RPC_VERSION_REG] = version;
+}
+
+uint64_t ts_rpc_abi_get_memory_handle(const uint32_t regs[5])
+{
+ return (uint64_t)regs[TS_RPC_MEMORY_HANDLE_MSW_REG] << 32 |
+ regs[TS_RPC_MEMORY_HANDLE_LSW_REG];
+}
+
+void ts_rpc_abi_set_memory_handle(uint32_t regs[5], uint64_t handle)
+{
+ regs[TS_RPC_MEMORY_HANDLE_LSW_REG] = handle;
+ regs[TS_RPC_MEMORY_HANDLE_MSW_REG] = handle >> 32;
+}
+
+uint64_t ts_rpc_abi_get_memory_tag(const uint32_t regs[5])
+{
+ return (uint64_t)regs[TS_RPC_MEMORY_TAG_MSW_REG] << 32 | regs[TS_RPC_MEMORY_TAG_LSW_REG];
+}
+
+void ts_rpc_abi_set_memory_tag(uint32_t regs[5], uint64_t tag)
+{
+ regs[TS_RPC_MEMORY_TAG_LSW_REG] = tag;
+ regs[TS_RPC_MEMORY_TAG_MSW_REG] = tag >> 32;
+}
+
+uint32_t ts_rpc_abi_get_rpc_status(const uint32_t regs[5])
+{
+ return regs[TS_RPC_RPC_STATUS_REG];
+}
+
+void ts_rpc_abi_set_rpc_status(uint32_t regs[5], uint32_t status)
+{
+ regs[TS_RPC_RPC_STATUS_REG] = status;
+}
+
+uint32_t ts_rpc_abi_get_service_status(const uint32_t regs[5])
+{
+ return regs[TS_RPC_SERVICE_STATUS_REG];
+}
+
+void ts_rpc_abi_set_service_status(uint32_t regs[5], uint32_t status)
+{
+ regs[TS_RPC_SERVICE_STATUS_REG] = status;
+}
+
+void ts_rpc_abi_get_uuid(const uint32_t regs[5], struct rpc_uuid *uuid)
+{
+ memcpy(uuid, ®s[TS_RPC_UUID_START_REG], sizeof(*uuid));
+}
+
+void ts_rpc_abi_set_uuid(uint32_t regs[5], const struct rpc_uuid *uuid)
+{
+ memcpy(®s[TS_RPC_UUID_START_REG], uuid, sizeof(*uuid));
+}
+
+uint8_t ts_rpc_abi_get_queried_interface_id(const uint32_t regs[5])
+{
+ return get_field(regs, TS_RPC_QUERIED_INTERFACE_ID_REG, TS_RPC_QUERIED_INTERFACE_ID_SHIFT,
+ TS_RPC_QUERIED_INTERFACE_ID_MASK);
+}
+
+void ts_rpc_abi_set_queried_interface_id(uint32_t regs[5], uint8_t interface_id)
+{
+ set_field(regs, TS_RPC_QUERIED_INTERFACE_ID_REG, TS_RPC_QUERIED_INTERFACE_ID_SHIFT,
+ TS_RPC_QUERIED_INTERFACE_ID_MASK, interface_id);
+}
+
+uint32_t ts_rpc_abi_get_request_length(const uint32_t regs[5])
+{
+ return regs[TS_RPC_REQUEST_LENGTH_REG];
+}
+
+void ts_rpc_abi_set_request_length(uint32_t regs[5], uint32_t length)
+{
+ regs[TS_RPC_REQUEST_LENGTH_REG] = length;
+}
+
+uint32_t ts_rpc_abi_get_client_id(const uint32_t regs[5])
+{
+ return regs[TS_RPC_CLIENT_ID_REG];
+}
+
+void ts_rpc_abi_set_client_id(uint32_t regs[5], uint32_t client_id)
+{
+ regs[TS_RPC_CLIENT_ID_REG] = client_id;
+}
+
+uint32_t ts_rpc_abi_get_response_length(const uint32_t regs[5])
+{
+ return regs[TS_RPC_RESPONSE_LENGTH_REG];
+}
+
+void ts_rpc_abi_set_response_length(uint32_t regs[5], uint32_t length)
+{
+ regs[TS_RPC_RESPONSE_LENGTH_REG] = length;
+}
diff --git a/components/rpc/ts_rpc/common/ts_rpc_abi.h b/components/rpc/ts_rpc/common/ts_rpc_abi.h
new file mode 100644
index 0000000..8b0fa1c
--- /dev/null
+++ b/components/rpc/ts_rpc/common/ts_rpc_abi.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TS_RPC_ABI_H
+#define TS_RPC_ABI_H
+
+#include "rpc_uuid.h"
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Trusted-services RPC ABI function
+ *
+ * This file contains getters and setters for TS ABI fields. They handle the five arg registers of
+ * the FF-A direct messages and extract or insert fields of suitable types.
+ */
+
+#define TS_RPC_ABI_FLAG_FAST_CALL (0x01)
+
+#define TS_RPC_ABI_MANAGEMENT_OPCODE_VERSION (0)
+#define TS_RPC_ABI_MANAGEMENT_OPCODE_MEMORY_RETRIEVE (1)
+#define TS_RPC_ABI_MANAGEMENT_OPCODE_MEMORY_RELINQUISH (2)
+#define TS_RPC_ABI_MANAGEMENT_OPCODE_INTERFACE_ID_QUERY (3)
+
+#define TS_RPC_ABI_VERSION_V1 (1)
+
+uint8_t ts_rpc_abi_get_flags(const uint32_t regs[5]);
+void ts_rpc_abi_set_flags(uint32_t regs[5], uint8_t flags);
+
+uint8_t ts_rpc_abi_get_interface_id(const uint32_t regs[5]);
+void ts_rpc_abi_set_interface_id(uint32_t regs[5], uint8_t interface_id);
+
+bool ts_rpc_abi_is_management_interface_id(const uint32_t regs[5]);
+void ts_rpc_abi_set_management_interface_id(uint32_t regs[5]);
+
+uint16_t ts_rpc_abi_get_opcode(const uint32_t regs[5]);
+void ts_rpc_abi_set_opcode(uint32_t regs[5], uint16_t interface_id);
+
+void ts_rpc_abi_copy_control_reg(uint32_t response_regs[5], const uint32_t request_regs[5]);
+
+uint32_t ts_rpc_abi_get_version(const uint32_t regs[5]);
+void ts_rpc_abi_set_version(uint32_t regs[5], uint32_t version);
+
+uint64_t ts_rpc_abi_get_memory_handle(const uint32_t regs[5]);
+void ts_rpc_abi_set_memory_handle(uint32_t regs[5], uint64_t handle);
+
+uint64_t ts_rpc_abi_get_memory_tag(const uint32_t regs[5]);
+void ts_rpc_abi_set_memory_tag(uint32_t regs[5], uint64_t tag);
+
+uint32_t ts_rpc_abi_get_rpc_status(const uint32_t regs[5]);
+void ts_rpc_abi_set_rpc_status(uint32_t regs[5], uint32_t status);
+
+uint32_t ts_rpc_abi_get_service_status(const uint32_t regs[5]);
+void ts_rpc_abi_set_service_status(uint32_t regs[5], uint32_t status);
+
+void ts_rpc_abi_get_uuid(const uint32_t regs[5], struct rpc_uuid *uuid);
+void ts_rpc_abi_set_uuid(uint32_t regs[5], const struct rpc_uuid *uuid);
+
+uint8_t ts_rpc_abi_get_queried_interface_id(const uint32_t regs[5]);
+void ts_rpc_abi_set_queried_interface_id(uint32_t regs[5], uint8_t interface_id);
+
+uint32_t ts_rpc_abi_get_request_length(const uint32_t regs[5]);
+void ts_rpc_abi_set_request_length(uint32_t regs[5], uint32_t length);
+
+uint32_t ts_rpc_abi_get_client_id(const uint32_t regs[5]);
+void ts_rpc_abi_set_client_id(uint32_t regs[5], uint32_t client_id);
+
+uint32_t ts_rpc_abi_get_response_length(const uint32_t regs[5]);
+void ts_rpc_abi_set_response_length(uint32_t regs[5], uint32_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TS_RPC_ABI_H */