1 /* 2 * Copyright (c) 2018-2022, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #ifndef __PSA_SERVICE_H__ 9 #define __PSA_SERVICE_H__ 10 11 #include <stddef.h> 12 #include <stdint.h> 13 14 #include "config_impl.h" 15 16 #include "psa/client.h" 17 #include "psa/error.h" 18 #include "psa/framework_feature.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /********************** PSA Secure Partition Macros and Types ****************/ 25 26 /** 27 * A timeout value that requests a polling wait operation. 28 */ 29 #define PSA_POLL (0x00000000u) 30 31 /** 32 * A timeout value that requests a blocking wait operation. 33 */ 34 #define PSA_BLOCK (0x80000000u) 35 36 /** 37 * A mask value that includes all Secure Partition signals. 38 */ 39 #define PSA_WAIT_ANY (0xFFFFFFFFu) 40 41 /** 42 * The signal number for the Secure Partition doorbell. 43 */ 44 #define PSA_DOORBELL (0x00000008u) 45 46 /* PSA message types */ 47 /* An IPC message type that indicates a new connection. */ 48 #define PSA_IPC_CONNECT (-1) 49 /* An IPC message type that indicates the end of a connection. */ 50 #define PSA_IPC_DISCONNECT (-2) 51 52 /* FLIH return types */ 53 #define PSA_FLIH_NO_SIGNAL ((psa_flih_result_t) 0) 54 #define PSA_FLIH_SIGNAL ((psa_flih_result_t) 1) 55 56 /* Store a set of one or more Secure Partition signals */ 57 typedef uint32_t psa_signal_t; 58 59 /* A type used to temporarily store a previous interrupt state. */ 60 typedef uint32_t psa_irq_status_t; 61 62 /* The type of the return value from an FLIH function */ 63 typedef uint32_t psa_flih_result_t; 64 65 /** 66 * Describe a message received by an RoT Service after calling \ref psa_get(). 67 */ 68 typedef struct psa_msg_t { 69 int32_t type; /* One of the following values: 70 * \ref PSA_IPC_CONNECT 71 * >= 0 72 * \ref PSA_IPC_DISCONNECT 73 */ 74 psa_handle_t handle; /* A reference generated by the SPM to the 75 * message returned by psa_get(). 76 */ 77 int32_t client_id; /* 78 * Partition ID of the sender of the 79 * message: 80 * - secure partition id; 81 * - non secure client endpoint id. 82 */ 83 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 84 void *rhandle; /* Be useful for binding a connection to some 85 * application-specific data or function 86 * pointer within the RoT Service 87 * implementation. 88 */ 89 #endif 90 size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input 91 * vector in bytes. 92 */ 93 size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output 94 * vector in bytes. 95 */ 96 } psa_msg_t; 97 98 /************************* PSA Secure Partition API **************************/ 99 100 /** 101 * \brief Return the Secure Partition interrupt signals that have been asserted 102 * from a subset of signals provided by the caller. 103 * 104 * \param[in] signal_mask A set of signals to query. Signals that are not 105 * in this set will be ignored. 106 * \param[in] timeout Specify either blocking \ref PSA_BLOCK or 107 * polling \ref PSA_POLL operation. 108 * 109 * \retval >0 At least one signal is asserted. 110 * \retval 0 No signals are asserted. This is only seen when 111 * a polling timeout is used. 112 */ 113 psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout); 114 115 /** 116 * \brief Retrieve the message which corresponds to a given RoT Service signal 117 * and remove the message from the RoT Service queue. 118 * 119 * \param[in] signal The signal value for an asserted RoT Service. 120 * \param[out] msg Pointer to \ref psa_msg_t object for receiving 121 * the message. 122 * 123 * \retval PSA_SUCCESS Success, *msg will contain the delivered 124 * message. 125 * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered. 126 * \retval "PROGRAMMER ERROR" The call is invalid because one or more of the 127 * following are true: 128 * \arg signal has more than a single bit set. 129 * \arg signal does not correspond to an RoT Service. 130 * \arg The RoT Service signal is not currently 131 * asserted. 132 * \arg The msg pointer provided is not a valid memory 133 * reference. 134 */ 135 psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg); 136 137 /** 138 * \brief Associate some RoT Service private data with a client connection. 139 * 140 * \param[in] msg_handle Handle for the client's message. 141 * \param[in] rhandle Reverse handle allocated by the RoT Service. 142 * 143 * \retval void Success, rhandle will be provided with all 144 * subsequent messages delivered on this 145 * connection. 146 * \retval "PROGRAMMER ERROR" msg_handle is invalid. 147 */ 148 void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle); 149 150 /** 151 * \brief Read a message parameter or part of a message parameter from a client 152 * input vector. 153 * 154 * \param[in] msg_handle Handle for the client's message. 155 * \param[in] invec_idx Index of the input vector to read from. Must be 156 * less than \ref PSA_MAX_IOVEC. 157 * \param[out] buffer Buffer in the Secure Partition to copy the 158 * requested data to. 159 * \param[in] num_bytes Maximum number of bytes to be read from the 160 * client input vector. 161 * 162 * \retval >0 Number of bytes copied. 163 * \retval 0 There was no remaining data in this input 164 * vector. 165 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 166 * following are true: 167 * \arg msg_handle is invalid. 168 * \arg msg_handle does not refer to a 169 * \ref PSA_IPC_CALL message. 170 * \arg invec_idx is equal to or greater than 171 * \ref PSA_MAX_IOVEC. 172 * \arg the memory reference for buffer is invalid or 173 * not writable. 174 */ 175 size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, 176 void *buffer, size_t num_bytes); 177 178 /** 179 * \brief Skip over part of a client input vector. 180 * 181 * \param[in] msg_handle Handle for the client's message. 182 * \param[in] invec_idx Index of input vector to skip from. Must be 183 * less than \ref PSA_MAX_IOVEC. 184 * \param[in] num_bytes Maximum number of bytes to skip in the client 185 * input vector. 186 * 187 * \retval >0 Number of bytes skipped. 188 * \retval 0 There was no remaining data in this input 189 * vector. 190 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 191 * following are true: 192 * \arg msg_handle is invalid. 193 * \arg msg_handle does not refer to a request 194 * message. 195 * \arg invec_idx is equal to or greater than 196 * \ref PSA_MAX_IOVEC. 197 */ 198 size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes); 199 200 /** 201 * \brief Write a message response to a client output vector. 202 * 203 * \param[in] msg_handle Handle for the client's message. 204 * \param[out] outvec_idx Index of output vector in message to write to. 205 * Must be less than \ref PSA_MAX_IOVEC. 206 * \param[in] buffer Buffer with the data to write. 207 * \param[in] num_bytes Number of bytes to write to the client output 208 * vector. 209 * 210 * \retval void Success 211 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 212 * following are true: 213 * \arg msg_handle is invalid. 214 * \arg msg_handle does not refer to a request 215 * message. 216 * \arg outvec_idx is equal to or greater than 217 * \ref PSA_MAX_IOVEC. 218 * \arg The memory reference for buffer is invalid. 219 * \arg The call attempts to write data past the end 220 * of the client output vector. 221 */ 222 void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, 223 const void *buffer, size_t num_bytes); 224 225 /** 226 * \brief Complete handling of a specific message and unblock the client. 227 * 228 * \param[in] msg_handle Handle for the client's message. 229 * \param[in] status Message result value to be reported to the 230 * client. 231 * 232 * \retval void Success. 233 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 234 * following are true: 235 * \arg msg_handle is invalid. 236 * \arg An invalid status code is specified for the 237 * type of message. 238 */ 239 void psa_reply(psa_handle_t msg_handle, psa_status_t status); 240 241 /** 242 * \brief Send a PSA_DOORBELL signal to a specific Secure Partition. 243 * 244 * \param[in] partition_id Secure Partition ID of the target partition. 245 * 246 * \retval void Success. 247 * \retval "PROGRAMMER ERROR" partition_id does not correspond to a Secure 248 * Partition. 249 */ 250 void psa_notify(int32_t partition_id); 251 252 /** 253 * \brief Clear the PSA_DOORBELL signal. 254 * 255 * \retval void Success. 256 * \retval "PROGRAMMER ERROR" The Secure Partition's doorbell signal is not 257 * currently asserted. 258 */ 259 void psa_clear(void); 260 261 /** 262 * \brief Inform the SPM that an interrupt has been handled (end of interrupt). 263 * 264 * \param[in] irq_signal The interrupt signal that has been processed. 265 * 266 * \retval void Success. 267 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 268 * following are true: 269 * \arg irq_signal is not an interrupt signal. 270 * \arg irq_signal indicates more than one signal. 271 * \arg irq_signal is not currently asserted. 272 * \arg The interrupt is not using SLIH. 273 */ 274 void psa_eoi(psa_signal_t irq_signal); 275 276 /** 277 * \brief Terminate execution within the calling Secure Partition and will not 278 * return. 279 * 280 * \retval "Does not return" 281 */ 282 void psa_panic(void); 283 284 /** 285 * \brief Enable an interrupt. 286 * 287 * \param[in] irq_signal The signal for the interrupt to be enabled. 288 * This must have a single bit set, which must be the 289 * signal value for an interrupt in the calling Secure 290 * Partition. 291 * 292 * \retval void 293 * \retval "PROGRAMMER ERROR" If one or more of the following are true: 294 * \arg \a irq_signal is not an interrupt signal. 295 * \arg \a irq_signal indicates more than one signal. 296 */ 297 void psa_irq_enable(psa_signal_t irq_signal); 298 299 /** 300 * \brief Disable an interrupt and return the status of the interrupt prior to 301 * being disabled by this call. 302 * 303 * \param[in] irq_signal The signal for the interrupt to be disabled. 304 * This must have a single bit set, which must be the 305 * signal value for an interrupt in the calling Secure 306 * Partition. 307 * 308 * \retval 0 The interrupt was disabled prior to this call. 309 * 1 The interrupt was enabled prior to this call. 310 * \retval "PROGRAMMER ERROR" If one or more of the following are true: 311 * \arg \a irq_signal is not an interrupt signal. 312 * \arg \a irq_signal indicates more than one signal. 313 * 314 * \note The current implementation always return 1. Do not use the return. 315 */ 316 psa_irq_status_t psa_irq_disable(psa_signal_t irq_signal); 317 318 /** 319 * \brief Reset the signal for an interrupt that is using FLIH handling. 320 * 321 * \param[in] irq_signal The interrupt signal to be reset. 322 * This must have a single bit set, corresponding to a 323 * currently asserted signal for an interrupt that is 324 * defined to use FLIH handling. 325 * 326 * \retval void 327 * \retval "Programmer Error" if one or more of the following are true: 328 * \arg \a irq_signal is not a signal for an interrupt 329 * that is specified with FLIH handling in the Secure 330 * Partition manifest. 331 * \arg \a irq_signal indicates more than one signal. 332 * \arg \a irq_signal is not currently asserted. 333 */ 334 void psa_reset_signal(psa_signal_t irq_signal); 335 336 #if PSA_FRAMEWORK_HAS_MM_IOVEC 337 338 /** 339 * \brief Map a client input vector for direct access by a Secure Partition RoT 340 * Service. 341 * 342 * \param[in] msg_handle Handle for the client's message. 343 * \param[in] invec_idx Index of input vector to map. Must be 344 * less than \ref PSA_MAX_IOVEC. 345 * 346 * \retval A pointer to the input vector data. 347 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 348 * following are true: 349 * \arg MM-IOVEC has not been enabled for the RoT 350 * Service that received the message. 351 * \arg msg_handle is invalid. 352 * \arg msg_handle does not refer to a request 353 * message. 354 * \arg invec_idx is equal to or greater than 355 * \ref PSA_MAX_IOVEC. 356 * \arg The input vector has length zero. 357 * \arg The input vector has already been mapped using 358 * psa_map_invec(). 359 * \arg The input vector has already been accessed 360 * using psa_read() or psa_skip(). 361 */ 362 const void *psa_map_invec(psa_handle_t msg_handle, uint32_t invec_idx); 363 364 /** 365 * \brief Unmap a previously mapped client input vector from a Secure Partition 366 * RoT Service. 367 * 368 * \param[in] msg_handle Handle for the client's message. 369 * \param[in] invec_idx Index of input vector to map. Must be 370 * less than \ref PSA_MAX_IOVEC. 371 * 372 * \retval void 373 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 374 * following are true: 375 * \arg msg_handle is invalid. 376 * \arg msg_handle does not refer to a request 377 * message. 378 * \arg invec_idx is equal to or greater than 379 * \ref PSA_MAX_IOVEC. 380 * \arg The input vector has not been mapped by a call 381 * to psa_map_invec(). 382 * \arg The input vector has already been unmapped by 383 * a call to psa_unmap_invec(). 384 */ 385 void psa_unmap_invec(psa_handle_t msg_handle, uint32_t invec_idx); 386 387 /** 388 * \brief Map a client output vector for direct access by a Secure Partition RoT 389 * Service. 390 * 391 * \param[in] msg_handle Handle for the client's message. 392 * \param[in] outvec_idx Index of output vector to map. Must be 393 * less than \ref PSA_MAX_IOVEC. 394 * 395 * \retval A pointer to the output vector data. 396 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 397 * following are true: 398 * \arg MM-IOVEC has not been enabled for the RoT 399 * Service that received the message. 400 * \arg msg_handle is invalid. 401 * \arg msg_handle does not refer to a request 402 * message. 403 * \arg outvec_idx is equal to or greater than 404 * \ref PSA_MAX_IOVEC. 405 * \arg The output vector has length zero. 406 * \arg The output vector has already been mapped 407 * using psa_map_outvec(). 408 * \arg The output vector has already been accessed 409 * using psa_write(). 410 */ 411 void *psa_map_outvec(psa_handle_t msg_handle, uint32_t outvec_idx); 412 413 /** 414 * \brief Unmap a previously mapped client output vector from a Secure Partition 415 * RoT Service. 416 * 417 * \param[in] msg_handle Handle for the client's message. 418 * \param[in] outvec_idx Index of output vector to map. Must be 419 * less than \ref PSA_MAX_IOVEC. 420 * \param[in] len The number of bytes written to the output 421 * vector. This must be less than or equal to the 422 * size of the output vector. 423 * 424 * \retval void 425 * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the 426 * following are true: 427 * \arg msg_handle is invalid. 428 * \arg msg_handle does not refer to a request 429 * message. 430 * \arg outvec_idx is equal to or greater than 431 * \ref PSA_MAX_IOVEC. 432 * \arg The output vector has not been mapped by a 433 * call to psa_map_outvec(). 434 * \arg The output vector has already been unmapped by 435 * a call to psa_unmap_outvec(). 436 */ 437 void psa_unmap_outvec(psa_handle_t msg_handle, uint32_t outvec_idx, size_t len); 438 439 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */ 440 441 #ifdef __cplusplus 442 } 443 #endif 444 445 #endif /* __PSA_SERVICE_H__ */ 446