diff options
author | Julian Hall <julian.hall@arm.com> | 2020-11-23 17:50:47 +0100 |
---|---|---|
committer | Gyorgy Szing <Gyorgy.Szing@arm.com> | 2020-11-27 16:47:02 +0100 |
commit | 6c59e4e7de6f047cec83ed4fab7a8af94276f092 (patch) | |
tree | 9e9877d15f6ec9ae3eed1dac82eb912dc8258a84 | |
parent | 07679f2dedd45801ba3bc155685617d177ecbbba (diff) | |
download | trusted-services-6c59e4e7de6f047cec83ed4fab7a8af94276f092.tar.gz |
Add generic RPC layer
Adds generic RPC caller and endpoint. This is the base for specialized
RPC communication using e.g. FF-A messaging. The protocol description
is implemented in two flavours: packed C structures and protobuf.
Change-Id: I17f450b7272bd4008fc20fe8f716a253f6754000
Signed-off-by: Julian Hall <julian.hall@arm.com>
-rw-r--r-- | components/rpc/common/caller/component.cmake | 13 | ||||
-rw-r--r-- | components/rpc/common/caller/rpc_caller.c | 25 | ||||
-rw-r--r-- | components/rpc/common/endpoint/call_ep.h | 134 | ||||
-rw-r--r-- | components/rpc/common/interface/component.cmake | 18 | ||||
-rw-r--r-- | components/rpc/common/interface/rpc_caller.h | 80 | ||||
-rw-r--r-- | components/rpc/common/interface/rpc_status.h | 28 | ||||
-rw-r--r-- | protocols/rpc/common/packed-c/component.cmake | 14 | ||||
-rw-r--r-- | protocols/rpc/common/packed-c/status.h | 28 | ||||
-rw-r--r-- | protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp | 33 | ||||
-rw-r--r-- | protocols/rpc/common/packed-c/test/component.cmake | 14 | ||||
-rw-r--r-- | protocols/rpc/common/protobuf/component.cmake | 13 | ||||
-rw-r--r-- | protocols/rpc/common/protobuf/status.proto | 22 |
12 files changed, 422 insertions, 0 deletions
diff --git a/components/rpc/common/caller/component.cmake b/components/rpc/common/caller/component.cmake new file mode 100644 index 000000000..9cb5138fd --- /dev/null +++ b/components/rpc/common/caller/component.cmake @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------------- +# 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() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/rpc_caller.c" + ) diff --git a/components/rpc/common/caller/rpc_caller.c b/components/rpc/common/caller/rpc_caller.c new file mode 100644 index 000000000..4fd1e5adf --- /dev/null +++ b/components/rpc/common/caller/rpc_caller.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <rpc_caller.h> +#include <stdint.h> + +rpc_call_handle rpc_caller_begin(struct rpc_caller *s, + uint8_t **req_buf, size_t req_len) +{ + return s->call_begin(s->context, req_buf, req_len); +} + +rpc_status_t rpc_caller_invoke(struct rpc_caller *s, rpc_call_handle handle, + uint32_t opcode, int *opstatus, uint8_t **resp_buf, size_t *resp_len) +{ + return s->call_invoke(s->context, handle, opcode, opstatus, resp_buf, resp_len); +} + +void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle) +{ + s->call_end(s->context, handle); +} diff --git a/components/rpc/common/endpoint/call_ep.h b/components/rpc/common/endpoint/call_ep.h new file mode 100644 index 000000000..1b5d03dc4 --- /dev/null +++ b/components/rpc/common/endpoint/call_ep.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CALL_EP_H +#define CALL_EP_H + +#include <stddef.h> +#include <stdint.h> +#include <rpc_status.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions related to an rpc call endpoint */ + +/** \brief Call parameter buffer + * + * Describes a buffer for holding call request and response parameters. + */ +struct call_param_buf { + size_t size; + size_t data_len; + void *data; +}; + +static inline struct call_param_buf call_param_buf_init_empty(void *data, size_t size) +{ + struct call_param_buf v; + + v.size = size; + v.data_len = 0; + v.data = data; + + return v; +} + +static inline struct call_param_buf call_param_buf_init_full(void *data, + size_t size, + size_t data_len) +{ + struct call_param_buf v; + + v.size = size; + v.data_len = data_len; + v.data = data; + + return v; +} + +/** \brief Serializer for handling call parameters + * + * An abstract serializer pointer, used for attaching a concrete + * serializer to a call request for serializing/deserializing call + * parameters. The strategy for selecting an appropriate serializer + * could be hard-coded or dynamic, based on a content type identifier + * carried by a concrete rpc. + */ +typedef const void* call_param_serializer_ptr; + +/** \brief Call request + * + * A call request object represents a request from a client that will + * be handled by a call endpoint. + */ +struct call_req { + uint32_t caller_id; + uint32_t opcode; + int opstatus; + call_param_serializer_ptr serializer; + struct call_param_buf req_buf; + struct call_param_buf resp_buf; +}; + +static inline uint32_t call_req_get_caller_id(const struct call_req *req) +{ + return req->caller_id; +} + +static inline uint32_t call_req_get_opcode(const struct call_req *req) +{ + return req->opcode; +} + +static inline int call_req_get_opstatus(const struct call_req *req) +{ + return req->opstatus; +} + +static inline void call_req_set_opstatus(struct call_req *req, int opstatus) +{ + req->opstatus = opstatus; +} + +static inline call_param_serializer_ptr call_req_get_serializer(const struct call_req *req) +{ + return req->serializer; +} + +static inline struct call_param_buf *call_req_get_req_buf(struct call_req *req) +{ + return &req->req_buf; +} + +static inline struct call_param_buf *call_req_get_resp_buf(struct call_req *req) +{ + return &req->resp_buf; +} + +/** \brief Call endpoint + * + * A generalized call endpoint. Provides a standard interface for a + * call endpoint that handles incoming call requests. + */ +struct call_ep +{ + void *context; + rpc_status_t (*receive)(struct call_ep *ep, struct call_req *req); +}; + +static inline rpc_status_t call_ep_receive(struct call_ep *ep, + struct call_req *req) +{ + return ep->receive(ep, req); +} + +#ifdef __cplusplus +} +#endif + +#endif /* CALL_EP_H */ diff --git a/components/rpc/common/interface/component.cmake b/components/rpc/common/interface/component.cmake new file mode 100644 index 000000000..d56760222 --- /dev/null +++ b/components/rpc/common/interface/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} PROPERTY RPC_CALLER_PUBLIC_HEADER_FILES + "${CMAKE_CURRENT_LIST_DIR}/rpc_caller.h" + "${CMAKE_CURRENT_LIST_DIR}/rpc_status.h" + ) + +target_include_directories(${TGT} PUBLIC + "${CMAKE_CURRENT_LIST_DIR}" + ) diff --git a/components/rpc/common/interface/rpc_caller.h b/components/rpc/common/interface/rpc_caller.h new file mode 100644 index 000000000..a75bdd9ab --- /dev/null +++ b/components/rpc/common/interface/rpc_caller.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPC_CALLER_H +#define RPC_CALLER_H + +#include <stddef.h> +#include <stdint.h> +#include "rpc_status.h" + +/* + * The rpc_caller puplic interface may be exported as a public interface to + * a shared library. + */ +#ifdef EXPORT_PUBLIC_INTERFACE_RPC_CALLER +#define RPC_CALLER_EXPORTED __attribute__((__visibility__("default"))) +#else +#define RPC_CALLER_EXPORTED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Defines an abstract interface for calling operations provided by an rpc endpoint. + * Concrete specializations will map the an RPC or direct calling mechanism to + * suite the deployment. + */ + +typedef void *rpc_call_handle; + +struct rpc_caller +{ + void *context; + + /* A concrete rpc_caller implements these methods */ + rpc_call_handle (*call_begin)(void *context, uint8_t **req_buf, size_t req_len); + + rpc_status_t (*call_invoke)(void *context, rpc_call_handle handle, uint32_t opcode, + int *opstatus, uint8_t **resp_buf, size_t *resp_len); + + void (*call_end)(void *context, rpc_call_handle handle); +}; + +/* + * Starts a call transaction. The returned handle is an identifier for the + * transaction and must be passed as a parameter to call_invoke() and + * call_end(). A concrete rpc_caller may perform resource allocation during + * this call. This will include a buffer for the request message parameters. + * Returns a NULL handle on failure. + */ +RPC_CALLER_EXPORTED rpc_call_handle rpc_caller_begin(struct rpc_caller *s, + uint8_t **req_buf, size_t req_len); + +/* + * Invokes the operation identified by the opcode. This method blocks + * until the operation completes. The status of the call is returned. An + * additional endpoint specific status value is also returned. If a response + * message was received, the concrete rpc_caller will have allocated a + * buffer for the reponse. This buffer will hold valid data until the point when + * call_end() is called for the transaction. + */ +RPC_CALLER_EXPORTED rpc_status_t rpc_caller_invoke(struct rpc_caller *s, rpc_call_handle handle, + uint32_t opcode, int *opstatus, uint8_t **resp_buf, size_t *resp_len); + +/* + * Ends the call transaction, allowing any resource associated with the + * transaction to be freed. + */ +RPC_CALLER_EXPORTED void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle); + +#ifdef __cplusplus +} +#endif + +#endif /* RPC_CALLER_H */ diff --git a/components/rpc/common/interface/rpc_status.h b/components/rpc/common/interface/rpc_status.h new file mode 100644 index 000000000..0405a64d1 --- /dev/null +++ b/components/rpc/common/interface/rpc_status.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPC_STATUS_H +#define RPC_STATUS_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief RPC status code type + * + * Used for returning the status of an RPC transaction. This is + * different from the opstatus which is used to return an endpoint + * specific status value. + */ +typedef int32_t rpc_status_t; + +#ifdef __cplusplus +} +#endif + +#endif /* RPC_STATUS_H */ diff --git a/protocols/rpc/common/packed-c/component.cmake b/protocols/rpc/common/packed-c/component.cmake new file mode 100644 index 000000000..041f7d549 --- /dev/null +++ b/protocols/rpc/common/packed-c/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# 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() + +target_include_directories(${TGT} + PRIVATE + "${CMAKE_CURRENT_LIST_DIR}" + ) diff --git a/protocols/rpc/common/packed-c/status.h b/protocols/rpc/common/packed-c/status.h new file mode 100644 index 000000000..7f7842995 --- /dev/null +++ b/protocols/rpc/common/packed-c/status.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PROTOCOLS_RPC_COMMON_STATUS_H +#define PROTOCOLS_RPC_COMMON_STATUS_H + +/* Common RPC status codes for C/C++ + * + * Alignment of these definitions with other defintions for + * alternative languages is checked through a set of test cases. + * These status values are aligned to PSA definitions. + */ +#define TS_RPC_CALL_ACCEPTED (0) +#define TS_RPC_ERROR_EP_DOES_NOT_EXIT (-1) +#define TS_RPC_ERROR_INVALID_OPCODE (-2) +#define TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED (-3) +#define TS_RPC_ERROR_INVALID_REQ_BODY (-4) +#define TS_RPC_ERROR_INVALID_RESP_BODY (-5) +#define TS_RPC_ERROR_RESOURCE_FAILURE (-6) +#define TS_RPC_ERROR_NOT_READY (-7) +#define TS_RPC_ERROR_INVALID_TRANSACTION (-8) +#define TS_RPC_ERROR_INTERNAL (-9) +#define TS_RPC_ERROR_INVALID_PARAMETER (-10) + +#endif /* PROTOCOLS_RPC_COMMON_STATUS_H */ diff --git a/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp b/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp new file mode 100644 index 000000000..c377957c0 --- /dev/null +++ b/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <rpc/common/protobuf/status.pb.h> +#include <protocols/rpc/common/packed-c/status.h> +#include <CppUTest/TestHarness.h> + +/* + * Check alignment of packed-c protocol values. + */ +TEST_GROUP(PackedCrpcCommonProtocolChecks) { + +}; + +TEST(PackedCrpcCommonProtocolChecks, checkRpcStatusCodes) { + + /* + * Check alignment between packed-c and protobuf rpc status codes + */ + CHECK_EQUAL(TS_RPC_CALL_ACCEPTED, ts_rpc_Status_CALL_ACCEPTED); + CHECK_EQUAL(TS_RPC_ERROR_EP_DOES_NOT_EXIT, ts_rpc_Status_ERROR_EP_DOES_NOT_EXIT); + CHECK_EQUAL(TS_RPC_ERROR_INVALID_OPCODE, ts_rpc_Status_ERROR_INVALID_OPCODE); + CHECK_EQUAL(TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED, ts_rpc_Status_ERROR_SERIALIZATION_NOT_SUPPORTED); + CHECK_EQUAL(TS_RPC_ERROR_INVALID_REQ_BODY, ts_rpc_Status_ERROR_INVALID_REQ_BODY); + CHECK_EQUAL(TS_RPC_ERROR_INVALID_RESP_BODY, ts_rpc_Status_ERROR_INVALID_RESP_BODY); + CHECK_EQUAL(TS_RPC_ERROR_RESOURCE_FAILURE, ts_rpc_Status_ERROR_RESOURCE_FAILURE); + CHECK_EQUAL(TS_RPC_ERROR_NOT_READY, ts_rpc_Status_ERROR_NOT_READY); + CHECK_EQUAL(TS_RPC_ERROR_INVALID_TRANSACTION, ts_rpc_Status_ERROR_INVALID_TRANSACTION); + CHECK_EQUAL(TS_RPC_ERROR_INTERNAL, ts_rpc_Status_ERROR_INTERNAL); + CHECK_EQUAL(TS_RPC_ERROR_INVALID_PARAMETER, ts_rpc_Status_ERROR_INVALID_PARAMETER); +}
\ No newline at end of file diff --git a/protocols/rpc/common/packed-c/test/component.cmake b/protocols/rpc/common/packed-c/test/component.cmake new file mode 100644 index 000000000..28a896bd4 --- /dev/null +++ b/protocols/rpc/common/packed-c/test/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# 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() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/check_rpc_status_packed-c.cpp" + ) + diff --git a/protocols/rpc/common/protobuf/component.cmake b/protocols/rpc/common/protobuf/component.cmake new file mode 100644 index 000000000..8155c2de1 --- /dev/null +++ b/protocols/rpc/common/protobuf/component.cmake @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------------- +# 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 PROTOBUF_FILES + "${CMAKE_CURRENT_LIST_DIR}/status.proto" + ) diff --git a/protocols/rpc/common/protobuf/status.proto b/protocols/rpc/common/protobuf/status.proto new file mode 100644 index 000000000..aa5cb08c1 --- /dev/null +++ b/protocols/rpc/common/protobuf/status.proto @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +syntax = "proto3"; + +package ts_rpc; + +/* Common RPC status codes */ +enum Status { + CALL_ACCEPTED = 0; + ERROR_EP_DOES_NOT_EXIT = -1; + ERROR_INVALID_OPCODE = -2; + ERROR_SERIALIZATION_NOT_SUPPORTED = -3; + ERROR_INVALID_REQ_BODY = -4; + ERROR_INVALID_RESP_BODY = -5; + ERROR_RESOURCE_FAILURE = -6; + ERROR_NOT_READY = -7; + ERROR_INVALID_TRANSACTION = -8; + ERROR_INTERNAL = -9; + ERROR_INVALID_PARAMETER = -10; +} |