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