blob: 16da007ac750775ffd7ce56795fbdfbbf8ac497c [file] [log] [blame]
Miklos Balint386b8b52017-11-29 13:12:32 +00001/*
Mate Toth-Pal5e6d0342019-11-22 11:43:20 +01002 * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
Miklos Balint386b8b52017-11-29 13:12:32 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#ifndef __SPM_API_H__
9#define __SPM_API_H__
10
11/* This file contains the apis exported by the SPM to tfm core */
Mate Toth-Pal3db437a2018-06-22 16:15:13 +020012#include "tfm_api.h"
Mingyang Sunc3123ec2020-06-11 17:43:58 +080013#include "spm_partition_defs.h"
David Hu49a28eb2019-08-14 18:18:15 +080014#include "tfm_secure_api.h"
Mingyang Sunf3d29892019-07-10 17:50:23 +080015#include <stdbool.h>
Edison Ai66fbdf12019-07-08 16:05:07 +080016#ifdef TFM_PSA_API
17#include "tfm_list.h"
18#include "tfm_wait.h"
Mingyang Sunf3d29892019-07-10 17:50:23 +080019#include "tfm_message_queue.h"
20#include "tfm_secure_api.h"
Summer Qinb5da9cc2019-08-26 15:19:45 +080021#include "tfm_thread.h"
Edison Ai66fbdf12019-07-08 16:05:07 +080022#endif
Miklos Balint386b8b52017-11-29 13:12:32 +000023
Mate Toth-Pal52674ab2018-02-26 09:47:56 +010024#define SPM_INVALID_PARTITION_IDX (~0U)
25
Summer Qineb537e52019-03-29 09:57:10 +080026/* Privileged definitions for partition thread mode */
27#define TFM_PARTITION_PRIVILEGED_MODE 1
28#define TFM_PARTITION_UNPRIVILEGED_MODE 0
29
Miklos Balint386b8b52017-11-29 13:12:32 +000030enum spm_err_t {
31 SPM_ERR_OK = 0,
Mate Toth-Pal349714a2018-02-23 15:30:24 +010032 SPM_ERR_PARTITION_DB_NOT_INIT,
33 SPM_ERR_PARTITION_ALREADY_ACTIVE,
34 SPM_ERR_PARTITION_NOT_AVAILABLE,
Hugues de Valonf704c802019-02-19 14:51:41 +000035 SPM_ERR_INVALID_PARAMETER,
Miklos Balint386b8b52017-11-29 13:12:32 +000036 SPM_ERR_INVALID_CONFIG,
37};
38
Hugues de Valon99578562019-06-18 16:08:51 +010039#define SPM_PARTITION_STATE_UNINIT 0
40#define SPM_PARTITION_STATE_IDLE 1
41#define SPM_PARTITION_STATE_RUNNING 2
42#define SPM_PARTITION_STATE_HANDLING_IRQ 3
43#define SPM_PARTITION_STATE_SUSPENDED 4
44#define SPM_PARTITION_STATE_BLOCKED 5
45#define SPM_PARTITION_STATE_CLOSED 6
Mate Toth-Pal65291f32018-02-23 14:35:22 +010046
Hugues de Valon99578562019-06-18 16:08:51 +010047#define SPM_PART_FLAG_APP_ROT 0x01
48#define SPM_PART_FLAG_PSA_ROT 0x02
49#define SPM_PART_FLAG_IPC 0x04
Mate Toth-Pal59398712018-02-28 17:06:40 +010050
Shawn Shancc39fcb2019-11-13 15:38:16 +080051#define TFM_HANDLE_STATUS_IDLE 0
52#define TFM_HANDLE_STATUS_ACTIVE 1
Shawn Shanadb02862019-12-10 11:04:33 +080053#define TFM_HANDLE_STATUS_CONNECT_ERROR 2
Shawn Shancc39fcb2019-11-13 15:38:16 +080054
Edison Ai66fbdf12019-07-08 16:05:07 +080055#ifndef TFM_PSA_API
Miklos Balint386b8b52017-11-29 13:12:32 +000056/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +020057 * \brief Holds the iovec parameters that are passed to a service
58 *
59 * \note The size of the structure is (and have to be) multiple of 8 bytes
60 */
61struct iovec_args_t {
62 psa_invec in_vec[PSA_MAX_IOVEC]; /*!< Array of psa_invec objects */
63 size_t in_len; /*!< Number psa_invec objects in in_vec
64 */
65 psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
66 size_t out_len; /*!< Number psa_outvec objects in out_vec
67 */
68};
Mingyang Sunda01a972019-07-12 17:32:59 +080069
70/* The size of this struct must be multiple of 4 bytes as it is stacked to an
71 * uint32_t[] array
72 */
73struct interrupted_ctx_stack_frame_t {
Mingyang Sunda01a972019-07-12 17:32:59 +080074 uint32_t partition_state;
75};
76
77/* The size of this struct must be multiple of 4 bytes as it is stacked to an
78 * uint32_t[] array
79 */
80struct handler_ctx_stack_frame_t {
81 uint32_t partition_state;
82 uint32_t caller_partition_idx;
83};
Edison Ai66fbdf12019-07-08 16:05:07 +080084#endif /* !define(TFM_PSA_API) */
Mate Toth-Pal3db437a2018-06-22 16:15:13 +020085
86/**
Mate Toth-Pal18b83922018-02-26 17:58:18 +010087 * \brief Runtime context information of a partition
88 */
89struct spm_partition_runtime_data_t {
Edison Ai66fbdf12019-07-08 16:05:07 +080090#ifdef TFM_PSA_API
Edison Ai66fbdf12019-07-08 16:05:07 +080091 uint32_t signals; /* Service signals had been triggered*/
TTornblom83d96372019-11-19 12:53:16 +010092 struct tfm_event_t signal_evnt; /* Event signal */
Edison Ai66fbdf12019-07-08 16:05:07 +080093 struct tfm_list_node_t service_list;/* Service list */
Summer Qin66f1e032020-01-06 15:40:03 +080094 struct tfm_core_thread_t sp_thrd; /* Thread object */
Shawn Shan9b0e0c72019-10-22 13:43:07 +080095 uint32_t assigned_signals; /* All assigned signals */
Edison Ai66fbdf12019-07-08 16:05:07 +080096#else /* TFM_PSA_API */
Mate Toth-Pal18b83922018-02-26 17:58:18 +010097 uint32_t partition_state;
Mate Toth-Pal52674ab2018-02-26 09:47:56 +010098 uint32_t caller_partition_idx;
Mate Toth-Pal21a74c92018-04-13 14:05:41 +020099 int32_t caller_client_id;
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100100 uint32_t stack_ptr;
Miklos Balintace4c3f2018-07-30 12:31:15 +0200101 uint32_t lr;
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200102 struct iovec_args_t iovec_args;
103 psa_outvec *orig_outvec;
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200104 uint32_t *ctx_stack_ptr;
Edison Ai66fbdf12019-07-08 16:05:07 +0800105#endif /* TFM_PSA_API */
106 uint32_t signal_mask; /*
107 * Service signal mask passed by
108 * psa_wait()
109 */
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100110};
111
Mingyang Sunda01a972019-07-12 17:32:59 +0800112#ifdef TFM_PSA_API
113
Mingyang Sunda01a972019-07-12 17:32:59 +0800114#define TFM_VERSION_POLICY_RELAXED 0
115#define TFM_VERSION_POLICY_STRICT 1
116
Edison Ai97115822019-08-01 14:22:19 +0800117#define TFM_CONN_HANDLE_MAX_NUM 16
Mingyang Sunda01a972019-07-12 17:32:59 +0800118
119/* RoT connection handle list */
120struct tfm_conn_handle_t {
Edison Ai9cc26242019-08-06 11:28:04 +0800121 void *rhandle; /* Reverse handle value */
Shawn Shancc39fcb2019-11-13 15:38:16 +0800122 uint32_t status; /*
Shawn Shanadb02862019-12-10 11:04:33 +0800123 * Status of handle, three valid
124 * options:
125 * TFM_HANDLE_STATUS_ACTIVE,
126 * TFM_HANDLE_STATUS_IDLE and
127 * TFM_HANDLE_STATUS_CONNECT_ERROR
Shawn Shancc39fcb2019-11-13 15:38:16 +0800128 */
Summer Qin1ce712a2019-10-14 18:04:05 +0800129 int32_t client_id; /*
130 * Partition ID of the sender of the
131 * message:
132 * - secure partition id;
133 * - non secure client endpoint id.
134 */
Edison Ai97115822019-08-01 14:22:19 +0800135 struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
Edison Ai9cc26242019-08-06 11:28:04 +0800136 struct tfm_spm_service_t *service; /* RoT service pointer */
137 struct tfm_list_node_t list; /* list node */
Mingyang Sunda01a972019-07-12 17:32:59 +0800138};
139
140/* Service database defined by manifest */
141struct tfm_spm_service_db_t {
142 char *name; /* Service name */
143 uint32_t partition_id; /* Partition ID which service belong to */
144 psa_signal_t signal; /* Service signal */
145 uint32_t sid; /* Service identifier */
146 bool non_secure_client; /* If can be called by non secure client */
Shawn Shancc39fcb2019-11-13 15:38:16 +0800147 uint32_t version; /* Service version */
148 uint32_t version_policy; /* Service version policy */
Mingyang Sunda01a972019-07-12 17:32:59 +0800149};
150
151/* RoT Service data */
152struct tfm_spm_service_t {
Summer Qine578c5b2019-08-16 16:42:16 +0800153 const struct tfm_spm_service_db_t *service_db;/* Service database pointer */
Mingyang Sunda01a972019-07-12 17:32:59 +0800154 struct spm_partition_desc_t *partition; /*
155 * Point to secure partition
156 * data
157 */
158 struct tfm_list_node_t handle_list; /* Service handle list */
159 struct tfm_msg_queue_t msg_queue; /* Message queue */
160 struct tfm_list_node_t list; /* For list operation */
161};
162#endif /* ifdef(TFM_PSA_API) */
163
164/*********************** common definitions ***********************/
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100165
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100166/**
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100167 * \brief Returns the index of the partition with the given partition ID.
Miklos Balint386b8b52017-11-29 13:12:32 +0000168 *
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100169 * \param[in] partition_id Partition id
Miklos Balint386b8b52017-11-29 13:12:32 +0000170 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100171 * \return the partition idx if partition_id is valid,
172 * \ref SPM_INVALID_PARTITION_IDX othervise
173 */
174uint32_t get_partition_idx(uint32_t partition_id);
175
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200176/**
Summer Qinb4a854d2019-05-29 15:31:22 +0800177 * \brief Get the id of the partition for its index from the db
178 *
179 * \param[in] partition_idx Partition index
180 *
181 * \return Partition ID for that partition
182 *
183 * \note This function doesn't check if partition_idx is valid.
184 */
185uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx);
186
187/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200188 * \brief Get the flags associated with a partition
189 *
190 * \param[in] partition_idx Partition index
191 *
192 * \return Flags associated with the partition
193 *
194 * \note This function doesn't check if partition_idx is valid.
195 */
196uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
197
Mingyang Sunda01a972019-07-12 17:32:59 +0800198/**
199 * \brief Initialize partition database
200 *
201 * \return Error code \ref spm_err_t
202 */
203enum spm_err_t tfm_spm_db_init(void);
204
205/**
206 * \brief Change the privilege mode for partition thread mode.
207 *
208 * \param[in] privileged Privileged mode,
209 * \ref TFM_PARTITION_PRIVILEGED_MODE
210 * and \ref TFM_PARTITION_UNPRIVILEGED_MODE
211 *
212 * \note Barrier instructions are not called by this function, and if
213 * it is called in thread mode, it might be necessary to call
Edison Ai7aff9e82019-07-11 14:56:46 +0800214 * them after this function returns.
Mingyang Sunda01a972019-07-12 17:32:59 +0800215 */
216void tfm_spm_partition_change_privilege(uint32_t privileged);
217
Mate Toth-Pal5e6d0342019-11-22 11:43:20 +0100218/**
219 * \brief Get the current partition mode.
220 *
221 * \param[in] partition_flags Flags of current partition
222 *
223 * \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode
224 * \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode
225 */
226uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags);
227
Summer Qin830c5542020-02-14 13:44:20 +0800228/**
229 * \brief Handle an SPM request by a secure service
230 * \param[in] svc_ctx The stacked SVC context
231 */
232void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx);
233
Mingyang Sunda01a972019-07-12 17:32:59 +0800234/*********************** library definitions ***********************/
235
Summer Qinb4a854d2019-05-29 15:31:22 +0800236#ifndef TFM_PSA_API
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200237/**
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200238 * \brief Save interrupted partition context on ctx stack
239 *
240 * \param[in] partition_idx Partition index
241 *
242 * \note This function doesn't check if partition_idx is valid.
243 * \note This function doesn't whether the ctx stack overflows.
244 */
245void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx);
246
247/**
248 * \brief Restores interrupted partition context on ctx stack
249 *
250 * \param[in] partition_idx Partition index
251 *
252 * \note This function doesn't check if partition_idx is valid.
253 * \note This function doesn't whether the ctx stack underflows.
254 */
255void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx);
256
257/**
258 * \brief Save handler partition context on ctx stack
259 *
260 * \param[in] partition_idx Partition index
261 *
262 * \note This function doesn't check if partition_idx is valid.
263 * \note This function doesn't whether the ctx stack overflows.
264 */
265void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx);
266
267/**
268 * \brief Restores handler partition context on ctx stack
269 *
270 * \param[in] partition_idx Partition index
271 *
272 * \note This function doesn't check if partition_idx is valid.
273 * \note This function doesn't whether the ctx stack underflows.
274 */
275void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx);
276
277/**
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100278 * \brief Get the current runtime data of a partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100279 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100280 * \param[in] partition_idx Partition index
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100281 *
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100282 * \return The runtime data of the specified partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100283 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100284 * \note This function doesn't check if partition_idx is valid.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100285 */
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100286const struct spm_partition_runtime_data_t *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100287 tfm_spm_partition_get_runtime_data(uint32_t partition_idx);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100288
289/**
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100290 * \brief Returns the index of the partition that has running state
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100291 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100292 * \return The index of the partition with the running state, if there is any
293 * set. 0 otherwise.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100294 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100295uint32_t tfm_spm_partition_get_running_partition_idx(void);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100296
297/**
Miklos Balintace4c3f2018-07-30 12:31:15 +0200298 * \brief Save stack pointer and link register for partition in database
299 *
300 * \param[in] partition_idx Partition index
301 * \param[in] stack_ptr Stack pointer to be stored
302 * \param[in] lr Link register to be stored
303 *
304 * \note This function doesn't check if partition_idx is valid.
305 */
306void tfm_spm_partition_store_context(uint32_t partition_idx,
307 uint32_t stack_ptr, uint32_t lr);
308
309/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100310 * \brief Set the current state of a partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100311 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100312 * \param[in] partition_idx Partition index
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100313 * \param[in] state The state to be set
314 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100315 * \note This function doesn't check if partition_idx is valid.
Gyorgy Szing40a7af02019-02-06 14:19:47 +0100316 * \note The state has to have the value set of \ref spm_part_state_t.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100317 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100318void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100319
320/**
Miklos Balint6a139ae2018-04-04 19:44:37 +0200321 * \brief Set the caller partition index for a given partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100322 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100323 * \param[in] partition_idx Partition index
Miklos Balint6a139ae2018-04-04 19:44:37 +0200324 * \param[in] caller_partition_idx The index of the caller partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100325 *
Miklos Balint6a139ae2018-04-04 19:44:37 +0200326 * \note This function doesn't check if any of the partition_idxs are valid.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100327 */
Miklos Balint6a139ae2018-04-04 19:44:37 +0200328void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
329 uint32_t caller_partition_idx);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100330
331/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800332 * \brief Set the caller client ID for a given partition
333 *
334 * \param[in] partition_idx Partition index
335 * \param[in] caller_client_id The ID of the calling client
336 *
337 * \note This function doesn't check if any of the partition_idxs are valid.
338 */
Mate Toth-Pal21a74c92018-04-13 14:05:41 +0200339void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
340 int32_t caller_client_id);
341
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100342
343/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200344 * \brief Set the iovec parameters for the partition
345 *
346 * \param[in] partition_idx Partition index
347 * \param[in] args The arguments of the secure function
348 *
349 * args is expected to be of type int32_t[4] where:
350 * args[0] is in_vec
351 * args[1] is in_len
352 * args[2] is out_vec
353 * args[3] is out_len
354 *
Hugues de Valonf704c802019-02-19 14:51:41 +0000355 * \return Error code \ref spm_err_t
356 *
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200357 * \note This function doesn't check if partition_idx is valid.
358 * \note This function assumes that the iovecs that are passed in args are
359 * valid, and does no sanity check on them at all.
360 */
Hugues de Valonf704c802019-02-19 14:51:41 +0000361enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
362 const int32_t *args);
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200363
364/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100365 * \brief Execute partition init function
Miklos Balint386b8b52017-11-29 13:12:32 +0000366 *
367 * \return Error code \ref spm_err_t
368 */
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100369enum spm_err_t tfm_spm_partition_init(void);
Miklos Balint386b8b52017-11-29 13:12:32 +0000370
371/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100372 * \brief Clears the context info from the database for a partition.
Miklos Balint386b8b52017-11-29 13:12:32 +0000373 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100374 * \param[in] partition_idx Partition index
Miklos Balint386b8b52017-11-29 13:12:32 +0000375 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100376 * \note This function doesn't check if partition_idx is valid.
Miklos Balint386b8b52017-11-29 13:12:32 +0000377 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100378void tfm_spm_partition_cleanup_context(uint32_t partition_idx);
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200379
380/**
381 * \brief Set the signal mask for a given partition
382 *
383 * \param[in] partition_idx Partition index
384 * \param[in] signal_mask The signal mask to be set for the partition
385 *
386 * \note This function doesn't check if any of the partition_idxs are valid.
387 */
388void tfm_spm_partition_set_signal_mask(uint32_t partition_idx,
389 uint32_t signal_mask);
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800390
391/**
392 * \brief Signal that secure partition initialisation is finished
393 */
394void tfm_spm_secure_api_init_done(void);
395
396/**
397 * \brief Called if veneer is running in thread mode
398 */
399uint32_t tfm_spm_partition_request_svc_handler(
400 const uint32_t *svc_args, uint32_t lr);
401
402/**
403 * \brief Called when secure service returns
404 */
405uint32_t tfm_spm_partition_return_handler(uint32_t lr);
406
407/**
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800408 * \brief Stores caller's client id in state context
409 */
410void tfm_spm_get_caller_client_id_handler(uint32_t *svc_args);
411
412/**
413 * \brief Checks if a secure service's access to a memory location is permitted
414 */
415void tfm_spm_memory_permission_check_handler(uint32_t *svc_args);
416
417/**
418 * \brief Check whether a buffer is ok for writing to by the privileged API
419 * function.
420 *
421 * This function checks whether the caller partition owns the buffer, can write
422 * to it, and the buffer has proper alignment.
423 *
424 * \param[in] partition_idx Partition index
425 * \param[in] start_addr The start address of the buffer
426 * \param[in] len The length of the buffer
427 * \param[in] alignment The expected alignment (in bits)
428 *
429 * \return 1 if the check passes, 0 otherwise.
430 *
431 * \note For a 0 long buffer the check fails.
432 */
433int32_t tfm_spm_check_buffer_access(uint32_t partition_idx,
434 void *start_addr,
435 size_t len,
436 uint32_t alignment);
437
438/**
439 * \brief Handle deprivileged request
440 */
441extern uint32_t tfm_spm_depriv_req_handler(uint32_t *svc_args,
442 uint32_t excReturn);
443
444/**
445 * \brief Handle request to return to privileged
446 */
447uint32_t tfm_spm_depriv_return_handler(uint32_t *irq_svc_args, uint32_t lr);
448
449/**
450 * \brief Handle IRQ enable request
451 */
452void tfm_spm_enable_irq_handler(uint32_t *svc_args);
453
454/**
455 * \brief Handle IRQ disable request
456 */
457void tfm_spm_disable_irq_handler(uint32_t *svc_args);
458
459/**
460 * \brief Handle signal wait request
461 */
462void tfm_spm_psa_wait(uint32_t *svc_args);
463
464/**
465 * \brief Handle request to record IRQ processed
466 */
467void tfm_spm_psa_eoi(uint32_t *svc_args);
Summer Qinb4a854d2019-05-29 15:31:22 +0800468#endif /* !defined(TFM_PSA_API) */
469
Mingyang Sunf3d29892019-07-10 17:50:23 +0800470#ifdef TFM_PSA_API
Mingyang Sunda01a972019-07-12 17:32:59 +0800471/*************************** IPC definitions **************************/
Edison Ai7aff9e82019-07-11 14:56:46 +0800472
473/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800474 * \brief Get the running partition ID.
475 *
476 * \return Returns the partition ID
477 */
478uint32_t tfm_spm_partition_get_running_partition_id(void);
479
Mingyang Sunf3d29892019-07-10 17:50:23 +0800480/******************** Service handle management functions ********************/
481
482/**
483 * \brief Create connection handle for client connect
484 *
485 * \param[in] service Target service context pointer
Summer Qin1ce712a2019-10-14 18:04:05 +0800486 * \param[in] client_id Partition ID of the sender of the message
Mingyang Sunf3d29892019-07-10 17:50:23 +0800487 *
Summer Qin630c76b2020-05-20 10:32:58 +0800488 * \retval NULL Create failed
489 * \retval "Not NULL" Service handle created
Mingyang Sunf3d29892019-07-10 17:50:23 +0800490 */
Summer Qin630c76b2020-05-20 10:32:58 +0800491struct tfm_conn_handle_t *tfm_spm_create_conn_handle(
492 struct tfm_spm_service_t *service,
Summer Qin1ce712a2019-10-14 18:04:05 +0800493 int32_t client_id);
494
495/**
496 * \brief Validate connection handle for client connect
497 *
498 * \param[in] conn_handle Handle to be validated
499 * \param[in] client_id Partition ID of the sender of the message
500 *
501 * \retval IPC_SUCCESS Success
502 * \retval IPC_ERROR_GENERIC Invalid handle
503 */
Summer Qin630c76b2020-05-20 10:32:58 +0800504int32_t tfm_spm_validate_conn_handle(
505 const struct tfm_conn_handle_t *conn_handle,
506 int32_t client_id);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800507
Mingyang Sunf3d29892019-07-10 17:50:23 +0800508/******************** Partition management functions *************************/
509
510/**
511 * \brief Get current running partition context.
512 *
513 * \retval NULL Failed
514 * \retval "Not NULL" Return the parttion context pointer
515 * \ref spm_partition_desc_t structures
516 */
517struct spm_partition_desc_t *tfm_spm_get_running_partition(void);
518
519/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800520 * \brief Get the service context by service ID.
521 *
522 * \param[in] sid RoT Service identity
523 *
524 * \retval NULL Failed
525 * \retval "Not NULL" Target service context pointer,
526 * \ref tfm_spm_service_t structures
527 */
528struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
529
Mingyang Sunf3d29892019-07-10 17:50:23 +0800530/************************ Message functions **********************************/
531
532/**
Edison Ai97115822019-08-01 14:22:19 +0800533 * \brief Get message context by connect handle.
Mingyang Sunf3d29892019-07-10 17:50:23 +0800534 *
Edison Ai97115822019-08-01 14:22:19 +0800535 * \param[in] conn_handle Service connect handle.
536 *
537 * \return The message body context pointer
538 * \ref msg_body_t structures
539 */
540struct tfm_msg_body_t *
Summer Qin630c76b2020-05-20 10:32:58 +0800541 tfm_spm_get_msg_buffer_from_conn_handle(struct tfm_conn_handle_t *conn_handle);
Edison Ai97115822019-08-01 14:22:19 +0800542
543/**
544 * \brief Fill the message for PSA client call.
545 *
546 * \param[in] msg Service Message Queue buffer pointer
Mingyang Sunf3d29892019-07-10 17:50:23 +0800547 * \param[in] service Target service context pointer, which can be
548 * obtained by partition management functions
549 * \prarm[in] handle Connect handle return by psa_connect().
550 * \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
551 * PSA_IPC_DISCONNECT
Summer Qin1ce712a2019-10-14 18:04:05 +0800552 * \param[in] client_id Partition ID of the sender of the message
Mingyang Sunf3d29892019-07-10 17:50:23 +0800553 * \param[in] invec Array of input \ref psa_invec structures
554 * \param[in] in_len Number of input \ref psa_invec structures
555 * \param[in] outvec Array of output \ref psa_outvec structures
556 * \param[in] out_len Number of output \ref psa_outvec structures
557 * \param[in] caller_outvec Array of caller output \ref psa_outvec structures
Mingyang Sunf3d29892019-07-10 17:50:23 +0800558 */
Edison Ai97115822019-08-01 14:22:19 +0800559void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
560 struct tfm_spm_service_t *service,
Summer Qin630c76b2020-05-20 10:32:58 +0800561 struct tfm_conn_handle_t *handle,
Summer Qin1ce712a2019-10-14 18:04:05 +0800562 int32_t type, int32_t client_id,
Edison Ai97115822019-08-01 14:22:19 +0800563 psa_invec *invec, size_t in_len,
564 psa_outvec *outvec, size_t out_len,
565 psa_outvec *caller_outvec);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800566
567/**
568 * \brief Send message and wake up the SP who is waiting on
569 * message queue, block the current thread and
570 * scheduler triggered
571 *
572 * \param[in] service Target service context pointer, which can be
573 * obtained by partition management functions
574 * \param[in] msg message created by tfm_spm_create_msg()
575 * \ref tfm_msg_body_t structures
576 *
577 * \retval IPC_SUCCESS Success
578 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
579 * \retval IPC_ERROR_GENERIC Failed to enqueue message to service message queue
580 */
581int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
582 struct tfm_msg_body_t *msg);
583
584/**
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530585 * \brief Check the client version according to
Mingyang Sunf3d29892019-07-10 17:50:23 +0800586 * version policy
587 *
588 * \param[in] service Target service context pointer, which can be get
589 * by partition management functions
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530590 * \param[in] version Client support version
Mingyang Sunf3d29892019-07-10 17:50:23 +0800591 *
592 * \retval IPC_SUCCESS Success
593 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
594 * \retval IPC_ERROR_VERSION Check failed
595 */
596int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530597 uint32_t version);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800598
599/**
Edison Aie728fbf2019-11-13 09:37:12 +0800600 * \brief Check the client access authorization
601 *
602 * \param[in] sid Target RoT Service identity
603 * \param[in] service Target service context pointer, which can be get
604 * by partition management functions
605 * \param[in] ns_caller Whether from NS caller
606 *
607 * \retval IPC_SUCCESS Success
608 * \retval IPC_ERROR_GENERIC Authorization check failed
609 */
610int32_t tfm_spm_check_authorization(uint32_t sid,
611 struct tfm_spm_service_t *service,
Summer Qin618e8c32019-12-09 10:47:20 +0800612 bool ns_caller);
Edison Aie728fbf2019-11-13 09:37:12 +0800613
614/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800615 * \brief Check the memory reference is valid.
616 *
617 * \param[in] buffer Pointer of memory reference
618 * \param[in] len Length of memory reference in bytes
619 * \param[in] ns_caller From non-secure caller
620 * \param[in] access Type of access specified by the
621 * \ref tfm_memory_access_e
622 * \param[in] privileged Privileged mode or unprivileged mode:
623 * \ref TFM_PARTITION_UNPRIVILEGED_MODE
624 * \ref TFM_PARTITION_PRIVILEGED_MODE
625 *
626 * \retval IPC_SUCCESS Success
627 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
628 * \retval IPC_ERROR_MEMORY_CHECK Check failed
629 */
Summer Qin43c185d2019-10-10 15:44:42 +0800630int32_t tfm_memory_check(const void *buffer, size_t len, bool ns_caller,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800631 enum tfm_memory_access_e access,
632 uint32_t privileged);
633
Mingyang Sunf3d29892019-07-10 17:50:23 +0800634/*
635 * PendSV specified function.
636 *
637 * Parameters :
Summer Qind2ad7e72020-01-06 18:16:35 +0800638 * p_actx - Architecture context storage pointer
Mingyang Sunf3d29892019-07-10 17:50:23 +0800639 *
640 * Notes:
641 * This is a staging API. Scheduler should be called in SPM finally and
642 * this function will be obsoleted later.
643 */
Summer Qind2ad7e72020-01-06 18:16:35 +0800644void tfm_pendsv_do_schedule(struct tfm_arch_ctx_t *p_actx);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800645
Ken Liu490281d2019-12-30 15:55:26 +0800646/**
647 * \brief SPM initialization implementation
648 *
649 * \details This function must be called under handler mode.
Ken Liuce2692d2020-02-11 12:39:36 +0800650 * \retval This function returns an EXC_RETURN value. Other
651 * faults would panic the execution and never
652 * returned.
Ken Liu490281d2019-12-30 15:55:26 +0800653 */
Ken Liuce2692d2020-02-11 12:39:36 +0800654uint32_t tfm_spm_init(void);
Ken Liu490281d2019-12-30 15:55:26 +0800655
Shawn Shan6e7be072019-11-29 17:56:29 +0800656/*
657 * \brief This function get the current PSA RoT lifecycle state.
658 *
659 * \return state The current security lifecycle state of the PSA
660 * RoT. The PSA state and implementation state are
661 * encoded as follows:
662 * \arg state[15:8] – PSA lifecycle state
663 * \arg state[7:0] – IMPLEMENTATION DEFINED state
664 */
665uint32_t tfm_spm_get_lifecycle_state(void);
666
Mingyang Sund44522a2020-01-16 16:48:37 +0800667/* Svcall for PSA Client APIs */
668
669/**
670 * \brief SVC handler for \ref psa_framework_version.
671 *
672 * \return version The version of the PSA Framework implementation
673 * that is providing the runtime services to the
674 * caller.
675 */
676uint32_t tfm_spm_psa_framework_version(void);
677
678/**
679 * \brief SVC handler for \ref psa_version.
680 *
681 * \param[in] args Include all input arguments: sid.
682 * \param[in] ns_caller If 'true', call from non-secure client.
683 * Or from secure client.
684 *
685 * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
686 * caller is not permitted to access the service.
687 * \retval > 0 The version of the implemented RoT Service.
688 */
689uint32_t tfm_spm_psa_version(uint32_t *args, bool ns_caller);
690
691/**
692 * \brief SVC handler for \ref psa_connect.
693 *
694 * \param[in] args Include all input arguments:
695 * sid, version.
696 * \param[in] ns_caller If 'true', call from non-secure client.
697 * Or from secure client.
698 *
699 * \retval PSA_SUCCESS Success.
700 * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
701 * connection.
702 * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
703 * connection at the moment.
704 * \retval "Does not return" The RoT Service ID and version are not
705 * supported, or the caller is not permitted to
706 * access the service.
707 */
708psa_status_t tfm_spm_psa_connect(uint32_t *args, bool ns_caller);
709
710/**
711 * \brief SVC handler for \ref psa_call.
712 *
713 * \param[in] args Include all input arguments:
714 * handle, in_vec, in_len, out_vec, out_len.
715 * \param[in] ns_caller If 'true', call from non-secure client.
716 * Or from secure client.
717 * \param[in] lr EXC_RETURN value of the SVC.
718 *
719 * \retval >=0 RoT Service-specific status value.
720 * \retval <0 RoT Service-specific error code.
721 * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
722 * RoT Service. The call is a PROGRAMMER ERROR if
723 * one or more of the following are true:
724 * \arg An invalid handle was passed.
725 * \arg The connection is already handling a request.
726 * \arg type < 0.
727 * \arg An invalid memory reference was provided.
728 * \arg in_len + out_len > PSA_MAX_IOVEC.
729 * \arg The message is unrecognized by the RoT
730 * Service or incorrectly formatted.
731 */
732psa_status_t tfm_spm_psa_call(uint32_t *args, bool ns_caller, uint32_t lr);
733
734/**
735 * \brief SVC handler for \ref psa_close.
736 *
737 * \param[in] args Include all input arguments: handle.
738 * \param[in] ns_caller If 'true', call from non-secure client.
739 * Or from secure client.
740 *
741 * \retval void Success.
742 * \retval "Does not return" The call is invalid, one or more of the
743 * following are true:
744 * \arg An invalid handle was provided that is not
745 * the null handle.
746 * \arg The connection is handling a request.
747 */
748void tfm_spm_psa_close(uint32_t *args, bool ns_caller);
749
750/* Svcall for PSA Service APIs */
751
752/**
753 * \brief SVC handler for \ref psa_wait.
754 *
755 * \param[in] args Include all input arguments:
756 * signal_mask, timeout.
757 *
758 * \retval >0 At least one signal is asserted.
759 * \retval 0 No signals are asserted. This is only seen when
760 * a polling timeout is used.
761 */
762psa_signal_t tfm_spm_psa_wait(uint32_t *args);
763
764/**
765 * \brief SVC handler for \ref psa_get.
766 *
767 * \param[in] args Include all input arguments: signal, msg.
768 *
769 * \retval PSA_SUCCESS Success, *msg will contain the delivered
770 * message.
771 * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
772 * \retval "Does not return" The call is invalid because one or more of the
773 * following are true:
774 * \arg signal has more than a single bit set.
775 * \arg signal does not correspond to an RoT Service.
776 * \arg The RoT Service signal is not currently
777 * asserted.
778 * \arg The msg pointer provided is not a valid memory
779 * reference.
780 */
781psa_status_t tfm_spm_psa_get(uint32_t *args);
782
783/**
784 * \brief SVC handler for \ref psa_set_rhandle.
785 *
786 * \param[in] args Include all input arguments:
787 * msg_handle, rhandle.
788 *
789 * \retval void Success, rhandle will be provided with all
790 * subsequent messages delivered on this
791 * connection.
792 * \retval "Does not return" msg_handle is invalid.
793 */
794void tfm_spm_psa_set_rhandle(uint32_t *args);
795
796/**
797 * \brief SVC handler for \ref psa_read.
798 *
799 * \param[in] args Include all input arguments:
800 * msg_handle, invec_idx, buffer, num_bytes.
801 *
802 * \retval >0 Number of bytes copied.
803 * \retval 0 There was no remaining data in this input
804 * vector.
805 * \retval "Does not return" The call is invalid, one or more of the
806 * following are true:
807 * \arg msg_handle is invalid.
808 * \arg msg_handle does not refer to a request
809 * message.
810 * \arg invec_idx is equal to or greater than
811 * \ref PSA_MAX_IOVEC.
812 * \arg the memory reference for buffer is invalid or
813 * not writable.
814 */
815size_t tfm_spm_psa_read(uint32_t *args);
816
817/**
818 * \brief SVC handler for \ref psa_skip.
819 *
820 * \param[in] args Include all input arguments:
821 * msg_handle, invec_idx, num_bytes.
822 *
823 * \retval >0 Number of bytes skipped.
824 * \retval 0 There was no remaining data in this input
825 * vector.
826 * \retval "Does not return" The call is invalid, one or more of the
827 * following are true:
828 * \arg msg_handle is invalid.
829 * \arg msg_handle does not refer to a request
830 * message.
831 * \arg invec_idx is equal to or greater than
832 * \ref PSA_MAX_IOVEC.
833 */
834size_t tfm_spm_psa_skip(uint32_t *args);
835
836/**
837 * \brief SVC handler for \ref psa_write.
838 *
839 * \param[in] args Include all input arguments:
840 * msg_handle, outvec_idx, buffer, num_bytes.
841 *
842 * \retval void Success
843 * \retval "Does not return" The call is invalid, one or more of the
844 * following are true:
845 * \arg msg_handle is invalid.
846 * \arg msg_handle does not refer to a request
847 * message.
848 * \arg outvec_idx is equal to or greater than
849 * \ref PSA_MAX_IOVEC.
850 * \arg The memory reference for buffer is invalid.
851 * \arg The call attempts to write data past the end
852 * of the client output vector.
853 */
854void tfm_spm_psa_write(uint32_t *args);
855
856/**
857 * \brief SVC handler for \ref psa_reply.
858 *
859 * \param[in] args Include all input arguments:
860 * msg_handle, status.
861 *
862 * \retval void Success.
863 * \retval "Does not return" The call is invalid, one or more of the
864 * following are true:
865 * \arg msg_handle is invalid.
866 * \arg An invalid status code is specified for the
867 * type of message.
868 */
869void tfm_spm_psa_reply(uint32_t *args);
870
871/**
872 * \brief SVC handler for \ref psa_notify.
873 *
874 * \param[in] args Include all input arguments: partition_id.
875 *
876 * \retval void Success.
877 * \retval "Does not return" partition_id does not correspond to a Secure
878 * Partition.
879 */
880void tfm_spm_psa_notify(uint32_t *args);
881
882/**
883 * \brief SVC handler for \ref psa_clear.
884 *
885 * \retval void Success.
886 * \retval "Does not return" The Secure Partition's doorbell signal is not
887 * currently asserted.
888 */
889void tfm_spm_psa_clear(void);
890
891/**
892 * \brief SVC handler for \ref psa_eoi.
893 *
894 * \param[in] args Include all input arguments: irq_signal.
895 *
896 * \retval void Success.
897 * \retval "Does not return" The call is invalid, one or more of the
898 * following are true:
899 * \arg irq_signal is not an interrupt signal.
900 * \arg irq_signal indicates more than one signal.
901 * \arg irq_signal is not currently asserted.
902 */
903void tfm_spm_psa_eoi(uint32_t *args);
904
905/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800906 * \brief SVC handler of enabling irq_line of the specified irq_signal.
Mingyang Sund44522a2020-01-16 16:48:37 +0800907 *
908 * \param[in] args Include all input arguments: irq_signal.
909 *
910 * \retval void Success.
911 * \retval "Does not return" The call is invalid, one or more of the
912 * following are true:
913 * \arg irq_signal is not an interrupt signal.
914 * \arg irq_signal indicates more than one signal.
915 */
916void tfm_spm_enable_irq(uint32_t *args);
917
918/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800919 * \brief SVC handler of disabling irq_line of the specified irq_signal.
Mingyang Sund44522a2020-01-16 16:48:37 +0800920 *
921 * \param[in] args Include all input arguments: irq_signal.
922 *
923 * \retval void Success.
924 * \retval "Does not return" The call is invalid, one or more of the
925 * following are true:
926 * \arg irq_signal is not an interrupt signal.
927 * \arg irq_signal indicates more than one signal.
928 */
929void tfm_spm_disable_irq(uint32_t *args);
930
931/**
932 * \brief Validate the whether NS caller re-enter.
933 *
934 * \param[in] p_cur_sp Pointer to current partition.
935 * \param[in] p_ctx Pointer to current stack context.
936 * \param[in] exc_return EXC_RETURN value.
937 * \param[in] ns_caller If 'true', call from non-secure client.
938 * Or from secure client.
939 *
940 * \retval void Success.
941 */
942void tfm_spm_validate_caller(struct spm_partition_desc_t *p_cur_sp,
943 uint32_t *p_ctx, uint32_t exc_return,
944 bool ns_caller);
945
946/**
947 * \brief Terminate execution within the calling Secure Partition and will not
948 * return.
949 *
950 * \retval "Does not return"
951 */
952void tfm_spm_psa_panic(void);
953
Summer Qin373feb12020-03-27 15:35:33 +0800954/**
955 * \brief Converts a user handle into a corresponded handle instance.
956 */
957struct tfm_conn_handle_t *tfm_spm_to_handle_instance(psa_handle_t user_handle);
958
Mingyang Sund44522a2020-01-16 16:48:37 +0800959#endif /* defined(TFM_PSA_API) */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800960
Miklos Balint386b8b52017-11-29 13:12:32 +0000961#endif /*__SPM_API_H__ */