1Service Access Protocols 2======================== 3 4A trusted service is accessed by calling service-specific methods via an RPC mechanism. The set of callable methods forms the 5public interface exposed by a service. This section is concerned with interface conventions and protocols used for serializing 6method parameters and return values. It is anticipated that there will be a need to support different parameter serialization 7schemes to suite different needs. The project accommodates this with the following: 8 9 - The Protocols directory structure allows for different protocol definitions for the same service. 10 - Message serialization code is decoupled from service provider code using an abstract 'serializer' interface. Alternative 11 concrete serializers may provide implementations of the interface. 12 13A deployment independent interface for locating services and establishing RPC sessions is described here: :ref:`Service Locator` 14 15Trusted Services protocol layers 16-------------------------------- 17 18.. image:: image/TSProtocolLayers.svg 19 20* Service client interface: This component provides the interface to a given service for a user application, i.e. the PSA 21 Crypto, Internal Trusted Storage, etc. interface. 22 23* Service layer: This layer is responsible for serializing and deserializing the service specific parameters and it provides 24 a transparent interface between the caller and endpoint side. 25 26* RPC layer: 27 28 * RPC caller session: This component provides a session-like object for the service layer. After opening the session, it is 29 tied to the opened service interface of the endpoint. Each service call can use the simple begin/invoke/end interface for 30 requesting a buffer for the call parameters, for invoking the call and for releasing the response buffer. 31 32 The RPC caller session manages the lifetime of the shared memory. Currently it has two options. It either creates the 33 memory on session open and keeps it while the session is open, or it creates the shared buffer for each call and releases 34 it when the call ends (``end()``). 35 36 * RPC caller implementations (`ts_rpc_caller_linux`, `ts_rpc_caller_sp`, etc.): The RPC caller session is built on the 37 primitives of the RPC callers. These primitives allow the caller session finding the remote endpoint, creating and 38 releasing shared memories and doing the actual call. 39 40 The main RPC implementation is the TS RPC which is a TS specific RPC solution over FF-A. The project contains caller 41 implementations for Linux and for S-EL0 SPs. The Linux implementation is split between the user space and a kernel driver. 42 43 There are other RPC caller implementations (dummy, direct) which are used for testing purposes. 44 45 * RPC endpoint (`ts_rpc_endpoint_sp`): This component provides the RPC endpoint which can host multiple services. Once it 46 receives the call from the client, it finds the matching service and forwards the serialized call parameters to it. 47 48* FF-A layer: It is the transport layer of the protocol stack, and it provides interfaces for sending messages and sharing 49 memory between normal world and secure world components. 50 51TS RPC implementation 52--------------------- 53 54Generic concepts 55'''''''''''''''' 56 57* The requests are always sent by the caller and the endpoint sends a response. 58* The protocol version describes the ABI, the allowed values of the message fields and the behavior of the calls. 59* Service endpoints are provided by FF-A secure partitions. 60* Each endpoint can implement multiple services. The services are identified by their service UUID (**not** FF-A UUID). To 61 avoid including the UUID in each service call, a short interface ID is assigned to each service. The mapping of service 62 UUIDs and interface IDs can be queried by an RPC call. The lifetime of the interface ID is the same as the lifetime of the 63 service. The `0xff` interface ID is used for the management interface. 64* The service calls use shared memory to forward the call payload. It has to be shared via FF-A and then retrieved by the 65 endpoint. The shared memories are tied to an endpoint not to a service. 66* The errors which happen in the RPC layer will result in a RPC status code which indicates an error. 67* The errors which happen in the service handler will result in a service status code which indicates an error. In this case 68 the RPC status code will be `RPC_SUCCESS` as the RPC layer was able to forward the call between the service caller and the 69 service handler. 70 71ABI 72''' 73 74The ABI of the TS RPC protocol uses the 32 bit variants of ``FFA_MSG_SEND_DIRECT_REQ`` and ``FFA_MSG_SEND_DIRECT_RESP`` 75interfaces of the FF-A specification. The use of the implementation specific arguments is listed in the table below. 76 77.. list-table:: TS RPC ABI 78 :header-rows: 1 79 80 * - Message name 81 - Short message ID 82 - W3[31:30] - SAP 83 - W3[29:24] - Flags 84 - W3[23:16] - Interface ID 85 - W3[15:0] - Opcode 86 - W4 - Arg1 87 - W5 - Arg2 88 - W6 - Arg3 89 - W7 - Arg4 90 * - RPC protocol version get request 91 - ``VERSION_GET`` 92 - ``0b00`` 93 - ``0b000000`` 94 - ``0xff`` 95 - ``0x0000`` 96 - Reserved (MBZ) 97 - Reserved (MBZ) 98 - Reserved (MBZ) 99 - Reserved (MBZ) 100 * - RPC protocol version get response 101 - ``VERSION_GET`` 102 - ``0b00`` 103 - ``0b000000`` 104 - ``0xff`` 105 - ``0x0000`` 106 - Version, starting from ``0x00000001`` 107 - Reserved (MBZ) 108 - Reserved (MBZ) 109 - Reserved (MBZ) 110 * - Memory retrieve request 111 - ``MEM_RETRIEVE`` 112 - ``0b00`` 113 - ``0b000000`` 114 - ``0xff`` 115 - ``0x0001`` 116 - FF-A memory handle LSW 117 - FF-A memory handle MSW 118 - FF-A memory tag LSW 119 - FF-A memory tag MSW 120 * - Memory relinquish request 121 - ``MEM_RELINQUISH`` 122 - ``0b00`` 123 - ``0b000000`` 124 - ``0xff`` 125 - ``0x0002`` 126 - FF-A memory handle LSW 127 - FF-A memory handle MSW 128 - Reserved (MBZ) 129 - Reserved (MBZ) 130 * - Memory retrieve/relinquish response 131 - ``MEM_RETRIEVE``/``MEM_RELINQUISH`` 132 - ``0b00`` 133 - ``0b000000`` 134 - ``0xff`` 135 - ``0x0001``/``0x0002`` 136 - TS RPC status 137 - Reserved (MBZ) 138 - Reserved (MBZ) 139 - Reserved (MBZ) 140 * - Service info get request 141 - ``SERVICE_INFO_GET`` 142 - ``0b00`` 143 - ``0b000000`` 144 - ``0xff`` 145 - ``0x0003`` 146 - Service UUID 147 - Service UUID 148 - Service UUID 149 - Service UUID 150 * - Service info get response 151 - ``SERVICE_INFO_GET`` 152 - ``0b00`` 153 - ``0b000000`` 154 - ``0xff`` 155 - ``0x0003`` 156 - TS RPC status 157 - ``[31:8]`` Reserved 158 159 ``[7:0]`` Queried service interface ID 160 - Reserved (MBZ) 161 - Reserved (MBZ) 162 * - Service call request 163 - 164 - ``0b00`` 165 - ``0b000000`` 166 - Service interface ID 167 - Service opcode 168 - FF-A memory handle LSW 169 - FF-A memory handle MSW 170 - Request length 171 - Client ID 172 * - Service call response 173 - 174 - ``0b00`` 175 - ``0b000000`` 176 - Service interface ID 177 - Service opcode 178 - TS RPC status 179 - Service status 180 - Response length 181 - Reserved 182 183* **RPC protocol version get** 184 185 Queries the RPC protocol version. This message must be available and backwards compatible for all protocol versions. 186 187* **Memory retrieve** 188 189 Requests the endpoint to do an ``FFA_MEM_RETRIEVE_REQ`` call using the forwarded FF-A memory handle and tag. 190 191* **Memory relinquish** 192 193 Requests the endpoint to do an ``FFA_MEM_RELINQUISH`` call using the forwarded FF-A memory handle. 194 195* **Service info get** 196 197 Query service information from the endpoint by the UUID of the service. The UUID is transmitted as defined in SMCCC section 198 5.3 but in registers W4-W7. The returned service interface ID should be used in the service calls. Multiple endpoints can 199 implement the same service but one endpoint can implement a service only once. 200 201* **Service call** 202 203 After creating a shared memory and querying the interface ID for a given service UUID the caller can make a service call. The 204 service opcode and the contents of the shared memory is service specific. The request and response length fields indicate the 205 used area of the shared memory. 206 207 It is allowed to do a limited service call without shared memory, i.e. doorbell call. In this case the FF-A memory ID has to 208 be the invalid handle value ``0xffffffffffffffff``. 209 210Service discovery 211''''''''''''''''' 212 213* Query all TS SPs via ``FFA_PARTITION_INFO_GET`` call made to the SPMC. All TS SPs have the same FF-A UUID: 214 ``bdcd76d7-825e-4751-963b-86d4f84943ac`` If the system setup has fixed SP endpoint IDs, this step can be skipped. 215* Iterate thought the TS SPs and make a "Service info get request" RPC call to the SPs, containing the service UUID. If the 216 RPC status in the "Service info get response" is `RPC_SUCCESS`, the SP implements the service and its interface ID is returned 217 in the response. 218* If there are multiple instances of a service, the selection between these should be done in a service specific way (i.e. 219 query service version, capabilities, etc.). 220 221.. image:: image/TSServiceDiscovery.svg 222 223RPC status code values 224''''''''''''''''''''''' 225 226The status codes for the RPC layer are defined in `components/rpc/common/interface/rpc_status.h`. Currently the following values 227are defined: 228 229.. literalinclude:: ../../components/rpc/common/interface/rpc_status.h 230 :lines: 20-32 231 :language: C 232 233Example TS RPC call 234''''''''''''''''''' 235 236This example shows the full sequence of a service call by opening the RPC session, doing the call (begin/invoke/end) and then 237closing the session. In this case the RPC session it set to create individual shared memory for each call. 238 239.. uml:: uml/TSRPCCall.puml 240 241.. note:: 242 Although the TS RPC layer messages use ``FFA_MSG_SEND_DIRECT_REQ``/``FFA_MSG_SEND_DIRECT_RESP`` interface and go through the 243 SPMC their destination is not the SPMC but the RPC endpoint. For simplifying the diagram, these calls are showed as direct 244 calls between the TS RPC caller and the TS RPC endpoint. 245 246Status Codes 247------------ 248 249On returning from a request to invoke a service method, two status codes are returned: 250 251 - *RPC status* - A generic status code that corresponds to the RPC call transaction. RPC status codes are standardized across 252 all services. (See: `RPC status code values`_) 253 - *Service status* - a service specific status code. (See: `Service Status Codes`_ ) 254 255Separation of status codes by layer allows service specific status codes to be accommodated while keeping RPC status codes 256common. 257 258A client should only check the returned service status if the returned RPC status value is `RPC_SUCCESS`. All other RPC 259status values indicate that an error occurred in delivering the RPC request. An RPC status of `RPC_SUCCESS` does not 260indicate that the service was successful. It merely indicates that the request was delivered, a suitable handler was 261identified and the request parameters were understood. 262 263Service Access Protocol Definition Conventions 264---------------------------------------------- 265 266A service access protocol defines the following: 267 268 - Opcodes used for identifying service methods. 269 - Request parameters for each method. 270 - Response parameters for method return values. 271 - Operation status code. 272 273Details of how public interface definition files for trusted services are organized, see: :ref:`Project Structure` 274 275It is possible that for certain deployments, it will be necessary to customize which parameter encoding scheme is used. Many 276schemes are possible such as Protocol Buffers, CBOR, JSON, TLV, TPM commands or packed C structures. To make scheme 277customization straight forward, serialize/deserialize operations should be encapsulated behind a common interface to decouple 278service provider code from any particular serialization scheme. A section below describes a pattern for achieving this. 279 280Service Namespace 281''''''''''''''''' 282 283Definitions that form a service access protocol should live within a namespace that is unique for the particular service. Using 284a namespace for service definitions avoids possible clashes between similarly named definitions that belong to different 285services. How the namespace is implemented depends on how the access protocol is defined. For example, the Protocol Buffers 286definitions for the crypto service all live within the ts_crypto package. The recommended convention for forming a trusted 287service namespace is as follows:: 288 289 ts_<service_name> 290 291 e.g. 292 ts_crypto 293 ts_secure_storage 294 295Language Independent Protocol Definitions 296''''''''''''''''''''''''''''''''''''''''' 297 298By defining service access protocols using an interface description language (IDL) with good support for different programming 299languages, it should be straight forward to access trusted services from clients written in a range of languages. On Arm 300Cortex-A deployments, it is common for user applications to be implemented using a range of languages such as Go, Python or 301Java. Rather than relying on a binding to a C client library, native client code may be generated from the formal protocol 302definition files. Initial protocol definitions use Google Protocol Buffers as the IDL. The project structure allows for use of 303alternative definition schemes and serializations. 304 305Opcode Definition 306````````````````` 307 308Opcodes are integer values that identify methods implemented by a service endpoint. Opcodes only need to be unique within the 309scope of a particular service. The mapping of opcode to method is an important part of a service interface definition and 310should be readily available to clients written in a variety of programming languages. For a Protocol Buffers based definition, 311opcodes are defined in a file called:: 312 313 opcodes.proto 314 315For example, for the Crypto trusted service, the Protocol Buffers opcode definitions are in:: 316 317 protocols/service/crypto/protobuf/opcodes.proto 318 319Alternative definitions for light-weight C clients using the packed-c scheme are in:: 320 321 protocols/service/crypto/packed-c/opcodes.h 322 323Parameter Definition 324```````````````````` 325 326The convention used for serializing method parameters and return values may be specific to a particular service. The definition 327file will include message definitions for both request and response parameters. Common objects that are used for multiple 328methods should be defined in separate files. When using Protobufs, the following naming convention for method parameter files 329should be used:: 330 331 <method_name>.proto 332 333For example, the Crypto export_public_key method is defined in a file called:: 334 335 protocols/service/crypto/protobuf/export_public_key.proto 336 337Service Status Codes 338```````````````````` 339 340Service specific status code definitions using different definition schemes are defined here (using crypto service as an 341example):: 342 343 protocols/service/crypto/protobuf/status.proto 344 protocols/service/crypto/packed-c/status.h 345 346Status code definitions may also be shared between services. For example, services that conform to PSA API conventions will use 347standardized PSA status codes, defined here:: 348 349 protocols/service/psa/protobuf/status.proto 350 protocols/service/psa/packed-c/status.h 351 352Use of Protocol Buffers 353----------------------- 354 355When Protocol Buffers is used for protocol definition and parameter serialization, the following conventions have been adopted. 356 357.proto File Style Guide 358''''''''''''''''''''''' 359 360The style of the .proto files should follow Google's Protocol Buffers Style Guide. 361 362Protocol Buffer Library for Trusted Services 363'''''''''''''''''''''''''''''''''''''''''''' 364 365Protocol Buffers standardizes how service interfaces are defined and the on-wire encoding for messages. Because of this, service 366clients and service providers are free to use any conformant implementation. However for trusted services that may be deployed 367across a range of environments, some of which may be resource constrained, a lightweight library should be used for C/C++ code 368that implement or use trusted services. For this purpose, Nanobp (https://github.com/nanopb/nanopb) should be used. 369 370Serialization Protocol Flexibility 371---------------------------------- 372 373Many different serialization protocols exist for encoding and decoding message parameters. Hard-wiring a particular protocol 374into a trusted service provider implementation isn't desirable for the following reasons: 375 376 - Depending on the complexity of serialization operations, mixing serialization logic with protocol-independent code makes 377 trusted service provider code bigger and more difficult to maintain. 378 - Different protocols may be needed for different deployments. It should be possible to make a build-time or even a 379 run-time selection of which protocol to use. 380 - The number of supported serializations protocols is likely to grow. Adding a new protocol shouldn't require you to make 381 extensive code changes and definitely shouldn't break support for existing protocols. 382 383These problems can be avoided by implementing protocol specific operations behind a common interface. Serialize/deserialize 384operations will have the following pattern:: 385 386 int serialize_for_method(msg_buffer *buf, in args...); 387 int deserialize_for_method(const msg_buffer *buf, out args...); 388 389Encoding types are represented as dedicated service interfaces in the RPC protocol and as such are identified by a uniq 390service UUID. 391 392-------------- 393 394*Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.* 395 396SPDX-License-Identifier: BSD-3-Clause 397