blob: 1825a33ae3a11507e5485d535967b3ef2d00b560 [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
Summer Qin83214922020-06-22 15:07:08 +080056
57#define EXC_NUM_THREAD_MODE (0)
58#define EXC_NUM_SVCALL (11)
59#define EXC_NUM_PENDSV (14)
60#define EXC_NUM_SYSTICK (15)
61
Miklos Balint386b8b52017-11-29 13:12:32 +000062/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +020063 * \brief Holds the iovec parameters that are passed to a service
64 *
65 * \note The size of the structure is (and have to be) multiple of 8 bytes
66 */
67struct iovec_args_t {
68 psa_invec in_vec[PSA_MAX_IOVEC]; /*!< Array of psa_invec objects */
69 size_t in_len; /*!< Number psa_invec objects in in_vec
70 */
71 psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
72 size_t out_len; /*!< Number psa_outvec objects in out_vec
73 */
74};
Mingyang Sunda01a972019-07-12 17:32:59 +080075
76/* The size of this struct must be multiple of 4 bytes as it is stacked to an
77 * uint32_t[] array
78 */
79struct interrupted_ctx_stack_frame_t {
Mingyang Sunda01a972019-07-12 17:32:59 +080080 uint32_t partition_state;
81};
82
83/* The size of this struct must be multiple of 4 bytes as it is stacked to an
84 * uint32_t[] array
85 */
86struct handler_ctx_stack_frame_t {
87 uint32_t partition_state;
88 uint32_t caller_partition_idx;
89};
Edison Ai66fbdf12019-07-08 16:05:07 +080090#endif /* !define(TFM_PSA_API) */
Mate Toth-Pal3db437a2018-06-22 16:15:13 +020091
92/**
Mate Toth-Pal18b83922018-02-26 17:58:18 +010093 * \brief Runtime context information of a partition
94 */
95struct spm_partition_runtime_data_t {
Edison Ai66fbdf12019-07-08 16:05:07 +080096#ifdef TFM_PSA_API
Edison Ai66fbdf12019-07-08 16:05:07 +080097 uint32_t signals; /* Service signals had been triggered*/
TTornblom83d96372019-11-19 12:53:16 +010098 struct tfm_event_t signal_evnt; /* Event signal */
Edison Ai66fbdf12019-07-08 16:05:07 +080099 struct tfm_list_node_t service_list;/* Service list */
Summer Qin66f1e032020-01-06 15:40:03 +0800100 struct tfm_core_thread_t sp_thrd; /* Thread object */
Shawn Shan9b0e0c72019-10-22 13:43:07 +0800101 uint32_t assigned_signals; /* All assigned signals */
Edison Ai66fbdf12019-07-08 16:05:07 +0800102#else /* TFM_PSA_API */
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100103 uint32_t partition_state;
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100104 uint32_t caller_partition_idx;
Mate Toth-Pal21a74c92018-04-13 14:05:41 +0200105 int32_t caller_client_id;
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100106 uint32_t stack_ptr;
Miklos Balintace4c3f2018-07-30 12:31:15 +0200107 uint32_t lr;
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200108 struct iovec_args_t iovec_args;
109 psa_outvec *orig_outvec;
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200110 uint32_t *ctx_stack_ptr;
Edison Ai66fbdf12019-07-08 16:05:07 +0800111#endif /* TFM_PSA_API */
112 uint32_t signal_mask; /*
113 * Service signal mask passed by
114 * psa_wait()
115 */
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100116};
117
Mingyang Sunda01a972019-07-12 17:32:59 +0800118#ifdef TFM_PSA_API
119
Mingyang Sunda01a972019-07-12 17:32:59 +0800120#define TFM_VERSION_POLICY_RELAXED 0
121#define TFM_VERSION_POLICY_STRICT 1
122
Edison Ai97115822019-08-01 14:22:19 +0800123#define TFM_CONN_HANDLE_MAX_NUM 16
Mingyang Sunda01a972019-07-12 17:32:59 +0800124
125/* RoT connection handle list */
126struct tfm_conn_handle_t {
Edison Ai9cc26242019-08-06 11:28:04 +0800127 void *rhandle; /* Reverse handle value */
Shawn Shancc39fcb2019-11-13 15:38:16 +0800128 uint32_t status; /*
Shawn Shanadb02862019-12-10 11:04:33 +0800129 * Status of handle, three valid
130 * options:
131 * TFM_HANDLE_STATUS_ACTIVE,
132 * TFM_HANDLE_STATUS_IDLE and
133 * TFM_HANDLE_STATUS_CONNECT_ERROR
Shawn Shancc39fcb2019-11-13 15:38:16 +0800134 */
Summer Qin1ce712a2019-10-14 18:04:05 +0800135 int32_t client_id; /*
136 * Partition ID of the sender of the
137 * message:
138 * - secure partition id;
139 * - non secure client endpoint id.
140 */
Edison Ai97115822019-08-01 14:22:19 +0800141 struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
Edison Ai9cc26242019-08-06 11:28:04 +0800142 struct tfm_spm_service_t *service; /* RoT service pointer */
143 struct tfm_list_node_t list; /* list node */
Mingyang Sunda01a972019-07-12 17:32:59 +0800144};
145
146/* Service database defined by manifest */
147struct tfm_spm_service_db_t {
148 char *name; /* Service name */
149 uint32_t partition_id; /* Partition ID which service belong to */
150 psa_signal_t signal; /* Service signal */
151 uint32_t sid; /* Service identifier */
152 bool non_secure_client; /* If can be called by non secure client */
Shawn Shancc39fcb2019-11-13 15:38:16 +0800153 uint32_t version; /* Service version */
154 uint32_t version_policy; /* Service version policy */
Mingyang Sunda01a972019-07-12 17:32:59 +0800155};
156
157/* RoT Service data */
158struct tfm_spm_service_t {
Summer Qine578c5b2019-08-16 16:42:16 +0800159 const struct tfm_spm_service_db_t *service_db;/* Service database pointer */
Mingyang Sunda01a972019-07-12 17:32:59 +0800160 struct spm_partition_desc_t *partition; /*
161 * Point to secure partition
162 * data
163 */
164 struct tfm_list_node_t handle_list; /* Service handle list */
165 struct tfm_msg_queue_t msg_queue; /* Message queue */
166 struct tfm_list_node_t list; /* For list operation */
167};
168#endif /* ifdef(TFM_PSA_API) */
169
170/*********************** common definitions ***********************/
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100171
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100172/**
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100173 * \brief Returns the index of the partition with the given partition ID.
Miklos Balint386b8b52017-11-29 13:12:32 +0000174 *
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100175 * \param[in] partition_id Partition id
Miklos Balint386b8b52017-11-29 13:12:32 +0000176 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100177 * \return the partition idx if partition_id is valid,
178 * \ref SPM_INVALID_PARTITION_IDX othervise
179 */
180uint32_t get_partition_idx(uint32_t partition_id);
181
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200182/**
Summer Qinb4a854d2019-05-29 15:31:22 +0800183 * \brief Get the id of the partition for its index from the db
184 *
185 * \param[in] partition_idx Partition index
186 *
187 * \return Partition ID for that partition
188 *
189 * \note This function doesn't check if partition_idx is valid.
190 */
191uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx);
192
193/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200194 * \brief Get the flags associated with a partition
195 *
196 * \param[in] partition_idx Partition index
197 *
198 * \return Flags associated with the partition
199 *
200 * \note This function doesn't check if partition_idx is valid.
201 */
202uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
203
Mingyang Sunda01a972019-07-12 17:32:59 +0800204/**
205 * \brief Initialize partition database
206 *
207 * \return Error code \ref spm_err_t
208 */
209enum spm_err_t tfm_spm_db_init(void);
210
211/**
212 * \brief Change the privilege mode for partition thread mode.
213 *
214 * \param[in] privileged Privileged mode,
215 * \ref TFM_PARTITION_PRIVILEGED_MODE
216 * and \ref TFM_PARTITION_UNPRIVILEGED_MODE
217 *
218 * \note Barrier instructions are not called by this function, and if
219 * it is called in thread mode, it might be necessary to call
Edison Ai7aff9e82019-07-11 14:56:46 +0800220 * them after this function returns.
Mingyang Sunda01a972019-07-12 17:32:59 +0800221 */
222void tfm_spm_partition_change_privilege(uint32_t privileged);
223
Mate Toth-Pal5e6d0342019-11-22 11:43:20 +0100224/**
225 * \brief Get the current partition mode.
226 *
227 * \param[in] partition_flags Flags of current partition
228 *
229 * \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode
230 * \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode
231 */
232uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags);
233
Summer Qin830c5542020-02-14 13:44:20 +0800234/**
235 * \brief Handle an SPM request by a secure service
236 * \param[in] svc_ctx The stacked SVC context
237 */
238void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx);
239
Mingyang Sunda01a972019-07-12 17:32:59 +0800240/*********************** library definitions ***********************/
241
Summer Qinb4a854d2019-05-29 15:31:22 +0800242#ifndef TFM_PSA_API
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200243/**
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200244 * \brief Save interrupted partition context on ctx stack
245 *
246 * \param[in] partition_idx Partition index
247 *
248 * \note This function doesn't check if partition_idx is valid.
249 * \note This function doesn't whether the ctx stack overflows.
250 */
251void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx);
252
253/**
254 * \brief Restores interrupted partition context on ctx stack
255 *
256 * \param[in] partition_idx Partition index
257 *
258 * \note This function doesn't check if partition_idx is valid.
259 * \note This function doesn't whether the ctx stack underflows.
260 */
261void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx);
262
263/**
264 * \brief Save handler partition context on ctx stack
265 *
266 * \param[in] partition_idx Partition index
267 *
268 * \note This function doesn't check if partition_idx is valid.
269 * \note This function doesn't whether the ctx stack overflows.
270 */
271void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx);
272
273/**
274 * \brief Restores handler partition context on ctx stack
275 *
276 * \param[in] partition_idx Partition index
277 *
278 * \note This function doesn't check if partition_idx is valid.
279 * \note This function doesn't whether the ctx stack underflows.
280 */
281void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx);
282
283/**
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100284 * \brief Get the current runtime data of a partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100285 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100286 * \param[in] partition_idx Partition index
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100287 *
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100288 * \return The runtime data of the specified partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100289 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100290 * \note This function doesn't check if partition_idx is valid.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100291 */
Mate Toth-Pal18b83922018-02-26 17:58:18 +0100292const struct spm_partition_runtime_data_t *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100293 tfm_spm_partition_get_runtime_data(uint32_t partition_idx);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100294
295/**
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100296 * \brief Returns the index of the partition that has running state
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100297 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100298 * \return The index of the partition with the running state, if there is any
299 * set. 0 otherwise.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100300 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100301uint32_t tfm_spm_partition_get_running_partition_idx(void);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100302
303/**
Miklos Balintace4c3f2018-07-30 12:31:15 +0200304 * \brief Save stack pointer and link register for partition in database
305 *
306 * \param[in] partition_idx Partition index
307 * \param[in] stack_ptr Stack pointer to be stored
308 * \param[in] lr Link register to be stored
309 *
310 * \note This function doesn't check if partition_idx is valid.
311 */
312void tfm_spm_partition_store_context(uint32_t partition_idx,
313 uint32_t stack_ptr, uint32_t lr);
314
315/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100316 * \brief Set the current state of a partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100317 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100318 * \param[in] partition_idx Partition index
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100319 * \param[in] state The state to be set
320 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100321 * \note This function doesn't check if partition_idx is valid.
Gyorgy Szing40a7af02019-02-06 14:19:47 +0100322 * \note The state has to have the value set of \ref spm_part_state_t.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100323 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100324void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100325
326/**
Miklos Balint6a139ae2018-04-04 19:44:37 +0200327 * \brief Set the caller partition index for a given partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100328 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100329 * \param[in] partition_idx Partition index
Miklos Balint6a139ae2018-04-04 19:44:37 +0200330 * \param[in] caller_partition_idx The index of the caller partition
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100331 *
Miklos Balint6a139ae2018-04-04 19:44:37 +0200332 * \note This function doesn't check if any of the partition_idxs are valid.
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100333 */
Miklos Balint6a139ae2018-04-04 19:44:37 +0200334void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
335 uint32_t caller_partition_idx);
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100336
337/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800338 * \brief Set the caller client ID for a given partition
339 *
340 * \param[in] partition_idx Partition index
341 * \param[in] caller_client_id The ID of the calling client
342 *
343 * \note This function doesn't check if any of the partition_idxs are valid.
344 */
Mate Toth-Pal21a74c92018-04-13 14:05:41 +0200345void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
346 int32_t caller_client_id);
347
Mate Toth-Pal65291f32018-02-23 14:35:22 +0100348
349/**
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200350 * \brief Set the iovec parameters for the partition
351 *
352 * \param[in] partition_idx Partition index
353 * \param[in] args The arguments of the secure function
354 *
355 * args is expected to be of type int32_t[4] where:
356 * args[0] is in_vec
357 * args[1] is in_len
358 * args[2] is out_vec
359 * args[3] is out_len
360 *
Hugues de Valonf704c802019-02-19 14:51:41 +0000361 * \return Error code \ref spm_err_t
362 *
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200363 * \note This function doesn't check if partition_idx is valid.
364 * \note This function assumes that the iovecs that are passed in args are
365 * valid, and does no sanity check on them at all.
366 */
Hugues de Valonf704c802019-02-19 14:51:41 +0000367enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
368 const int32_t *args);
Mate Toth-Pal3db437a2018-06-22 16:15:13 +0200369
370/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100371 * \brief Execute partition init function
Miklos Balint386b8b52017-11-29 13:12:32 +0000372 *
373 * \return Error code \ref spm_err_t
374 */
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100375enum spm_err_t tfm_spm_partition_init(void);
Miklos Balint386b8b52017-11-29 13:12:32 +0000376
377/**
Mate Toth-Pal349714a2018-02-23 15:30:24 +0100378 * \brief Clears the context info from the database for a partition.
Miklos Balint386b8b52017-11-29 13:12:32 +0000379 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100380 * \param[in] partition_idx Partition index
Miklos Balint386b8b52017-11-29 13:12:32 +0000381 *
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100382 * \note This function doesn't check if partition_idx is valid.
Miklos Balint386b8b52017-11-29 13:12:32 +0000383 */
Mate Toth-Pal52674ab2018-02-26 09:47:56 +0100384void tfm_spm_partition_cleanup_context(uint32_t partition_idx);
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200385
386/**
387 * \brief Set the signal mask for a given partition
388 *
389 * \param[in] partition_idx Partition index
390 * \param[in] signal_mask The signal mask to be set for the partition
391 *
392 * \note This function doesn't check if any of the partition_idxs are valid.
393 */
394void tfm_spm_partition_set_signal_mask(uint32_t partition_idx,
395 uint32_t signal_mask);
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800396
397/**
398 * \brief Signal that secure partition initialisation is finished
399 */
400void tfm_spm_secure_api_init_done(void);
401
402/**
403 * \brief Called if veneer is running in thread mode
404 */
405uint32_t tfm_spm_partition_request_svc_handler(
406 const uint32_t *svc_args, uint32_t lr);
407
408/**
409 * \brief Called when secure service returns
410 */
411uint32_t tfm_spm_partition_return_handler(uint32_t lr);
412
413/**
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800414 * \brief Stores caller's client id in state context
415 */
416void tfm_spm_get_caller_client_id_handler(uint32_t *svc_args);
417
418/**
419 * \brief Checks if a secure service's access to a memory location is permitted
420 */
421void tfm_spm_memory_permission_check_handler(uint32_t *svc_args);
422
423/**
424 * \brief Check whether a buffer is ok for writing to by the privileged API
425 * function.
426 *
427 * This function checks whether the caller partition owns the buffer, can write
428 * to it, and the buffer has proper alignment.
429 *
430 * \param[in] partition_idx Partition index
431 * \param[in] start_addr The start address of the buffer
432 * \param[in] len The length of the buffer
433 * \param[in] alignment The expected alignment (in bits)
434 *
435 * \return 1 if the check passes, 0 otherwise.
436 *
437 * \note For a 0 long buffer the check fails.
438 */
439int32_t tfm_spm_check_buffer_access(uint32_t partition_idx,
440 void *start_addr,
441 size_t len,
442 uint32_t alignment);
443
444/**
445 * \brief Handle deprivileged request
446 */
447extern uint32_t tfm_spm_depriv_req_handler(uint32_t *svc_args,
448 uint32_t excReturn);
449
450/**
451 * \brief Handle request to return to privileged
452 */
453uint32_t tfm_spm_depriv_return_handler(uint32_t *irq_svc_args, uint32_t lr);
454
455/**
456 * \brief Handle IRQ enable request
457 */
458void tfm_spm_enable_irq_handler(uint32_t *svc_args);
459
460/**
461 * \brief Handle IRQ disable request
462 */
463void tfm_spm_disable_irq_handler(uint32_t *svc_args);
464
465/**
466 * \brief Handle signal wait request
467 */
468void tfm_spm_psa_wait(uint32_t *svc_args);
469
470/**
471 * \brief Handle request to record IRQ processed
472 */
473void tfm_spm_psa_eoi(uint32_t *svc_args);
Summer Qinb4a854d2019-05-29 15:31:22 +0800474#endif /* !defined(TFM_PSA_API) */
475
Mingyang Sunf3d29892019-07-10 17:50:23 +0800476#ifdef TFM_PSA_API
Mingyang Sunda01a972019-07-12 17:32:59 +0800477/*************************** IPC definitions **************************/
Edison Ai7aff9e82019-07-11 14:56:46 +0800478
479/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800480 * \brief Get the running partition ID.
481 *
482 * \return Returns the partition ID
483 */
484uint32_t tfm_spm_partition_get_running_partition_id(void);
485
Mingyang Sunf3d29892019-07-10 17:50:23 +0800486/******************** Service handle management functions ********************/
487
488/**
489 * \brief Create connection handle for client connect
490 *
491 * \param[in] service Target service context pointer
Summer Qin1ce712a2019-10-14 18:04:05 +0800492 * \param[in] client_id Partition ID of the sender of the message
Mingyang Sunf3d29892019-07-10 17:50:23 +0800493 *
Summer Qin630c76b2020-05-20 10:32:58 +0800494 * \retval NULL Create failed
495 * \retval "Not NULL" Service handle created
Mingyang Sunf3d29892019-07-10 17:50:23 +0800496 */
Summer Qin630c76b2020-05-20 10:32:58 +0800497struct tfm_conn_handle_t *tfm_spm_create_conn_handle(
498 struct tfm_spm_service_t *service,
Summer Qin1ce712a2019-10-14 18:04:05 +0800499 int32_t client_id);
500
501/**
502 * \brief Validate connection handle for client connect
503 *
504 * \param[in] conn_handle Handle to be validated
505 * \param[in] client_id Partition ID of the sender of the message
506 *
507 * \retval IPC_SUCCESS Success
508 * \retval IPC_ERROR_GENERIC Invalid handle
509 */
Summer Qin630c76b2020-05-20 10:32:58 +0800510int32_t tfm_spm_validate_conn_handle(
511 const struct tfm_conn_handle_t *conn_handle,
512 int32_t client_id);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800513
Mingyang Sunf3d29892019-07-10 17:50:23 +0800514/******************** Partition management functions *************************/
515
516/**
517 * \brief Get current running partition context.
518 *
519 * \retval NULL Failed
520 * \retval "Not NULL" Return the parttion context pointer
521 * \ref spm_partition_desc_t structures
522 */
523struct spm_partition_desc_t *tfm_spm_get_running_partition(void);
524
525/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800526 * \brief Get the service context by service ID.
527 *
528 * \param[in] sid RoT Service identity
529 *
530 * \retval NULL Failed
531 * \retval "Not NULL" Target service context pointer,
532 * \ref tfm_spm_service_t structures
533 */
534struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
535
Mingyang Sunf3d29892019-07-10 17:50:23 +0800536/************************ Message functions **********************************/
537
538/**
Edison Ai97115822019-08-01 14:22:19 +0800539 * \brief Get message context by connect handle.
Mingyang Sunf3d29892019-07-10 17:50:23 +0800540 *
Edison Ai97115822019-08-01 14:22:19 +0800541 * \param[in] conn_handle Service connect handle.
542 *
543 * \return The message body context pointer
544 * \ref msg_body_t structures
545 */
546struct tfm_msg_body_t *
Summer Qin630c76b2020-05-20 10:32:58 +0800547 tfm_spm_get_msg_buffer_from_conn_handle(struct tfm_conn_handle_t *conn_handle);
Edison Ai97115822019-08-01 14:22:19 +0800548
549/**
550 * \brief Fill the message for PSA client call.
551 *
552 * \param[in] msg Service Message Queue buffer pointer
Mingyang Sunf3d29892019-07-10 17:50:23 +0800553 * \param[in] service Target service context pointer, which can be
554 * obtained by partition management functions
555 * \prarm[in] handle Connect handle return by psa_connect().
556 * \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
557 * PSA_IPC_DISCONNECT
Summer Qin1ce712a2019-10-14 18:04:05 +0800558 * \param[in] client_id Partition ID of the sender of the message
Mingyang Sunf3d29892019-07-10 17:50:23 +0800559 * \param[in] invec Array of input \ref psa_invec structures
560 * \param[in] in_len Number of input \ref psa_invec structures
561 * \param[in] outvec Array of output \ref psa_outvec structures
562 * \param[in] out_len Number of output \ref psa_outvec structures
563 * \param[in] caller_outvec Array of caller output \ref psa_outvec structures
Mingyang Sunf3d29892019-07-10 17:50:23 +0800564 */
Edison Ai97115822019-08-01 14:22:19 +0800565void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
566 struct tfm_spm_service_t *service,
Ken Liu505b1702020-05-29 13:19:58 +0800567 psa_handle_t handle,
Summer Qin1ce712a2019-10-14 18:04:05 +0800568 int32_t type, int32_t client_id,
Edison Ai97115822019-08-01 14:22:19 +0800569 psa_invec *invec, size_t in_len,
570 psa_outvec *outvec, size_t out_len,
571 psa_outvec *caller_outvec);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800572
573/**
574 * \brief Send message and wake up the SP who is waiting on
575 * message queue, block the current thread and
576 * scheduler triggered
577 *
578 * \param[in] service Target service context pointer, which can be
579 * obtained by partition management functions
580 * \param[in] msg message created by tfm_spm_create_msg()
581 * \ref tfm_msg_body_t structures
582 *
583 * \retval IPC_SUCCESS Success
584 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
585 * \retval IPC_ERROR_GENERIC Failed to enqueue message to service message queue
586 */
587int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
588 struct tfm_msg_body_t *msg);
589
590/**
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530591 * \brief Check the client version according to
Mingyang Sunf3d29892019-07-10 17:50:23 +0800592 * version policy
593 *
594 * \param[in] service Target service context pointer, which can be get
595 * by partition management functions
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530596 * \param[in] version Client support version
Mingyang Sunf3d29892019-07-10 17:50:23 +0800597 *
598 * \retval IPC_SUCCESS Success
599 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
600 * \retval IPC_ERROR_VERSION Check failed
601 */
602int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
Jaykumar Pitambarbhai Patel3a986022019-10-08 17:37:15 +0530603 uint32_t version);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800604
605/**
Edison Aie728fbf2019-11-13 09:37:12 +0800606 * \brief Check the client access authorization
607 *
608 * \param[in] sid Target RoT Service identity
609 * \param[in] service Target service context pointer, which can be get
610 * by partition management functions
611 * \param[in] ns_caller Whether from NS caller
612 *
613 * \retval IPC_SUCCESS Success
614 * \retval IPC_ERROR_GENERIC Authorization check failed
615 */
616int32_t tfm_spm_check_authorization(uint32_t sid,
617 struct tfm_spm_service_t *service,
Summer Qin618e8c32019-12-09 10:47:20 +0800618 bool ns_caller);
Edison Aie728fbf2019-11-13 09:37:12 +0800619
620/**
Mingyang Sunf3d29892019-07-10 17:50:23 +0800621 * \brief Check the memory reference is valid.
622 *
623 * \param[in] buffer Pointer of memory reference
624 * \param[in] len Length of memory reference in bytes
625 * \param[in] ns_caller From non-secure caller
626 * \param[in] access Type of access specified by the
627 * \ref tfm_memory_access_e
628 * \param[in] privileged Privileged mode or unprivileged mode:
629 * \ref TFM_PARTITION_UNPRIVILEGED_MODE
630 * \ref TFM_PARTITION_PRIVILEGED_MODE
631 *
632 * \retval IPC_SUCCESS Success
633 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
634 * \retval IPC_ERROR_MEMORY_CHECK Check failed
635 */
Summer Qin43c185d2019-10-10 15:44:42 +0800636int32_t tfm_memory_check(const void *buffer, size_t len, bool ns_caller,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800637 enum tfm_memory_access_e access,
638 uint32_t privileged);
639
Mingyang Sunf3d29892019-07-10 17:50:23 +0800640/*
641 * PendSV specified function.
642 *
643 * Parameters :
Summer Qind2ad7e72020-01-06 18:16:35 +0800644 * p_actx - Architecture context storage pointer
Mingyang Sunf3d29892019-07-10 17:50:23 +0800645 *
646 * Notes:
647 * This is a staging API. Scheduler should be called in SPM finally and
648 * this function will be obsoleted later.
649 */
Summer Qind2ad7e72020-01-06 18:16:35 +0800650void tfm_pendsv_do_schedule(struct tfm_arch_ctx_t *p_actx);
Mingyang Sunf3d29892019-07-10 17:50:23 +0800651
Ken Liu490281d2019-12-30 15:55:26 +0800652/**
653 * \brief SPM initialization implementation
654 *
655 * \details This function must be called under handler mode.
Ken Liuce2692d2020-02-11 12:39:36 +0800656 * \retval This function returns an EXC_RETURN value. Other
657 * faults would panic the execution and never
658 * returned.
Ken Liu490281d2019-12-30 15:55:26 +0800659 */
Ken Liuce2692d2020-02-11 12:39:36 +0800660uint32_t tfm_spm_init(void);
Ken Liu490281d2019-12-30 15:55:26 +0800661
Shawn Shan6e7be072019-11-29 17:56:29 +0800662/*
663 * \brief This function get the current PSA RoT lifecycle state.
664 *
665 * \return state The current security lifecycle state of the PSA
666 * RoT. The PSA state and implementation state are
667 * encoded as follows:
668 * \arg state[15:8] – PSA lifecycle state
669 * \arg state[7:0] – IMPLEMENTATION DEFINED state
670 */
671uint32_t tfm_spm_get_lifecycle_state(void);
672
Mingyang Sund44522a2020-01-16 16:48:37 +0800673/* Svcall for PSA Client APIs */
674
675/**
676 * \brief SVC handler for \ref psa_framework_version.
677 *
678 * \return version The version of the PSA Framework implementation
679 * that is providing the runtime services to the
680 * caller.
681 */
682uint32_t tfm_spm_psa_framework_version(void);
683
684/**
685 * \brief SVC handler for \ref psa_version.
686 *
687 * \param[in] args Include all input arguments: sid.
688 * \param[in] ns_caller If 'true', call from non-secure client.
689 * Or from secure client.
690 *
691 * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
692 * caller is not permitted to access the service.
693 * \retval > 0 The version of the implemented RoT Service.
694 */
695uint32_t tfm_spm_psa_version(uint32_t *args, bool ns_caller);
696
697/**
698 * \brief SVC handler for \ref psa_connect.
699 *
700 * \param[in] args Include all input arguments:
701 * sid, version.
702 * \param[in] ns_caller If 'true', call from non-secure client.
703 * Or from secure client.
704 *
705 * \retval PSA_SUCCESS Success.
706 * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
707 * connection.
708 * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
709 * connection at the moment.
710 * \retval "Does not return" The RoT Service ID and version are not
711 * supported, or the caller is not permitted to
712 * access the service.
713 */
714psa_status_t tfm_spm_psa_connect(uint32_t *args, bool ns_caller);
715
716/**
717 * \brief SVC handler for \ref psa_call.
718 *
719 * \param[in] args Include all input arguments:
720 * handle, in_vec, in_len, out_vec, out_len.
721 * \param[in] ns_caller If 'true', call from non-secure client.
722 * Or from secure client.
723 * \param[in] lr EXC_RETURN value of the SVC.
724 *
725 * \retval >=0 RoT Service-specific status value.
726 * \retval <0 RoT Service-specific error code.
727 * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
728 * RoT Service. The call is a PROGRAMMER ERROR if
729 * one or more of the following are true:
730 * \arg An invalid handle was passed.
731 * \arg The connection is already handling a request.
732 * \arg type < 0.
733 * \arg An invalid memory reference was provided.
734 * \arg in_len + out_len > PSA_MAX_IOVEC.
735 * \arg The message is unrecognized by the RoT
736 * Service or incorrectly formatted.
737 */
738psa_status_t tfm_spm_psa_call(uint32_t *args, bool ns_caller, uint32_t lr);
739
740/**
741 * \brief SVC handler for \ref psa_close.
742 *
743 * \param[in] args Include all input arguments: handle.
744 * \param[in] ns_caller If 'true', call from non-secure client.
745 * Or from secure client.
746 *
747 * \retval void Success.
748 * \retval "Does not return" The call is invalid, one or more of the
749 * following are true:
750 * \arg An invalid handle was provided that is not
751 * the null handle.
752 * \arg The connection is handling a request.
753 */
754void tfm_spm_psa_close(uint32_t *args, bool ns_caller);
755
756/* Svcall for PSA Service APIs */
757
758/**
759 * \brief SVC handler for \ref psa_wait.
760 *
761 * \param[in] args Include all input arguments:
762 * signal_mask, timeout.
763 *
764 * \retval >0 At least one signal is asserted.
765 * \retval 0 No signals are asserted. This is only seen when
766 * a polling timeout is used.
767 */
768psa_signal_t tfm_spm_psa_wait(uint32_t *args);
769
770/**
771 * \brief SVC handler for \ref psa_get.
772 *
773 * \param[in] args Include all input arguments: signal, msg.
774 *
775 * \retval PSA_SUCCESS Success, *msg will contain the delivered
776 * message.
777 * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
778 * \retval "Does not return" The call is invalid because one or more of the
779 * following are true:
780 * \arg signal has more than a single bit set.
781 * \arg signal does not correspond to an RoT Service.
782 * \arg The RoT Service signal is not currently
783 * asserted.
784 * \arg The msg pointer provided is not a valid memory
785 * reference.
786 */
787psa_status_t tfm_spm_psa_get(uint32_t *args);
788
789/**
790 * \brief SVC handler for \ref psa_set_rhandle.
791 *
792 * \param[in] args Include all input arguments:
793 * msg_handle, rhandle.
794 *
795 * \retval void Success, rhandle will be provided with all
796 * subsequent messages delivered on this
797 * connection.
798 * \retval "Does not return" msg_handle is invalid.
799 */
800void tfm_spm_psa_set_rhandle(uint32_t *args);
801
802/**
803 * \brief SVC handler for \ref psa_read.
804 *
805 * \param[in] args Include all input arguments:
806 * msg_handle, invec_idx, buffer, num_bytes.
807 *
808 * \retval >0 Number of bytes copied.
809 * \retval 0 There was no remaining data in this input
810 * vector.
811 * \retval "Does not return" The call is invalid, one or more of the
812 * following are true:
813 * \arg msg_handle is invalid.
814 * \arg msg_handle does not refer to a request
815 * message.
816 * \arg invec_idx is equal to or greater than
817 * \ref PSA_MAX_IOVEC.
818 * \arg the memory reference for buffer is invalid or
819 * not writable.
820 */
821size_t tfm_spm_psa_read(uint32_t *args);
822
823/**
824 * \brief SVC handler for \ref psa_skip.
825 *
826 * \param[in] args Include all input arguments:
827 * msg_handle, invec_idx, num_bytes.
828 *
829 * \retval >0 Number of bytes skipped.
830 * \retval 0 There was no remaining data in this input
831 * vector.
832 * \retval "Does not return" The call is invalid, one or more of the
833 * following are true:
834 * \arg msg_handle is invalid.
835 * \arg msg_handle does not refer to a request
836 * message.
837 * \arg invec_idx is equal to or greater than
838 * \ref PSA_MAX_IOVEC.
839 */
840size_t tfm_spm_psa_skip(uint32_t *args);
841
842/**
843 * \brief SVC handler for \ref psa_write.
844 *
845 * \param[in] args Include all input arguments:
846 * msg_handle, outvec_idx, buffer, num_bytes.
847 *
848 * \retval void Success
849 * \retval "Does not return" The call is invalid, one or more of the
850 * following are true:
851 * \arg msg_handle is invalid.
852 * \arg msg_handle does not refer to a request
853 * message.
854 * \arg outvec_idx is equal to or greater than
855 * \ref PSA_MAX_IOVEC.
856 * \arg The memory reference for buffer is invalid.
857 * \arg The call attempts to write data past the end
858 * of the client output vector.
859 */
860void tfm_spm_psa_write(uint32_t *args);
861
862/**
863 * \brief SVC handler for \ref psa_reply.
864 *
865 * \param[in] args Include all input arguments:
866 * msg_handle, status.
867 *
868 * \retval void Success.
869 * \retval "Does not return" The call is invalid, one or more of the
870 * following are true:
871 * \arg msg_handle is invalid.
872 * \arg An invalid status code is specified for the
873 * type of message.
874 */
875void tfm_spm_psa_reply(uint32_t *args);
876
877/**
878 * \brief SVC handler for \ref psa_notify.
879 *
880 * \param[in] args Include all input arguments: partition_id.
881 *
882 * \retval void Success.
883 * \retval "Does not return" partition_id does not correspond to a Secure
884 * Partition.
885 */
886void tfm_spm_psa_notify(uint32_t *args);
887
888/**
889 * \brief SVC handler for \ref psa_clear.
890 *
891 * \retval void Success.
892 * \retval "Does not return" The Secure Partition's doorbell signal is not
893 * currently asserted.
894 */
895void tfm_spm_psa_clear(void);
896
897/**
898 * \brief SVC handler for \ref psa_eoi.
899 *
900 * \param[in] args Include all input arguments: irq_signal.
901 *
902 * \retval void Success.
903 * \retval "Does not return" The call is invalid, one or more of the
904 * following are true:
905 * \arg irq_signal is not an interrupt signal.
906 * \arg irq_signal indicates more than one signal.
907 * \arg irq_signal is not currently asserted.
908 */
909void tfm_spm_psa_eoi(uint32_t *args);
910
911/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800912 * \brief SVC handler of enabling irq_line of the specified irq_signal.
Mingyang Sund44522a2020-01-16 16:48:37 +0800913 *
914 * \param[in] args Include all input arguments: irq_signal.
915 *
916 * \retval void Success.
917 * \retval "Does not return" The call is invalid, one or more of the
918 * following are true:
919 * \arg irq_signal is not an interrupt signal.
920 * \arg irq_signal indicates more than one signal.
921 */
922void tfm_spm_enable_irq(uint32_t *args);
923
924/**
Mingyang Sunc3123ec2020-06-11 17:43:58 +0800925 * \brief SVC handler of disabling irq_line of the specified irq_signal.
Mingyang Sund44522a2020-01-16 16:48:37 +0800926 *
927 * \param[in] args Include all input arguments: irq_signal.
928 *
929 * \retval void Success.
930 * \retval "Does not return" The call is invalid, one or more of the
931 * following are true:
932 * \arg irq_signal is not an interrupt signal.
933 * \arg irq_signal indicates more than one signal.
934 */
935void tfm_spm_disable_irq(uint32_t *args);
936
937/**
938 * \brief Validate the whether NS caller re-enter.
939 *
940 * \param[in] p_cur_sp Pointer to current partition.
941 * \param[in] p_ctx Pointer to current stack context.
942 * \param[in] exc_return EXC_RETURN value.
943 * \param[in] ns_caller If 'true', call from non-secure client.
944 * Or from secure client.
945 *
946 * \retval void Success.
947 */
948void tfm_spm_validate_caller(struct spm_partition_desc_t *p_cur_sp,
949 uint32_t *p_ctx, uint32_t exc_return,
950 bool ns_caller);
951
952/**
953 * \brief Terminate execution within the calling Secure Partition and will not
954 * return.
955 *
956 * \retval "Does not return"
957 */
958void tfm_spm_psa_panic(void);
959
Summer Qin373feb12020-03-27 15:35:33 +0800960/**
Ken Liu505b1702020-05-29 13:19:58 +0800961 * \brief Converts a handle instance into a corresponded user handle.
962 */
963psa_handle_t tfm_spm_to_user_handle(struct tfm_conn_handle_t *handle_instance);
964
965/**
Summer Qin373feb12020-03-27 15:35:33 +0800966 * \brief Converts a user handle into a corresponded handle instance.
967 */
968struct tfm_conn_handle_t *tfm_spm_to_handle_instance(psa_handle_t user_handle);
969
Mingyang Sund44522a2020-01-16 16:48:37 +0800970#endif /* defined(TFM_PSA_API) */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800971
Miklos Balint386b8b52017-11-29 13:12:32 +0000972#endif /*__SPM_API_H__ */