Mistake on this page?
Report an issue in GitHub or email us
tfm_secure_api.h
1 /*
2  * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef __TFM_SECURE_API_H__
9 #define __TFM_SECURE_API_H__
10 
11 #include <arm_cmse.h>
12 #include "tfm_svc.h"
13 #include "secure_utilities.h"
14 #include "tfm_core.h"
15 #include "tfm_api.h"
16 #include "bl2/include/tfm_boot_status.h"
17 
18 /*!
19  * \def __tfm_secure_gateway_attributes__
20  *
21  * \brief Attributes for secure gateway functions
22  */
23 #define __tfm_secure_gateway_attributes__ \
24  __attribute__((cmse_nonsecure_entry, noinline, section("SFN")))
25 
26 /* Hide specific errors if not debugging */
27 #ifdef TFM_CORE_DEBUG
28 #define TFM_ERROR_STATUS(status) (status)
29 #else
30 #define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
31 #endif
32 
33 #define TFM_SFN_API_LEGACY 0
34 #define TFM_SFN_API_IOVEC 1
35 
36 #ifndef TFM_LVL
37 #error TFM_LVL is not defined!
38 #endif
39 
40 extern void tfm_secure_api_error_handler(void);
41 
42 typedef int32_t(*sfn_t)(int32_t, int32_t, int32_t, int32_t);
43 
44 struct tfm_sfn_req_s {
45  uint32_t sp_id;
46  sfn_t sfn;
47  int32_t *args;
48  uint32_t caller_part_idx;
49  int32_t iovec_api;
50  uint32_t ns_caller;
51 };
52 
53 enum tfm_buffer_share_region_e {
54  TFM_BUFFER_SHARE_DISABLE,
55  TFM_BUFFER_SHARE_NS_CODE,
56  TFM_BUFFER_SHARE_SCRATCH,
57  TFM_BUFFER_SHARE_PRIV, /* only for TCB in level 2, all in level 1 */
58  TFM_BUFFER_SHARE_DEFAULT,
59 };
60 
61 enum tfm_ns_region_e {
62  TFM_NS_REGION_CODE = 0,
63  TFM_NS_REGION_DATA,
64  TFM_NS_REGION_VENEER,
65  TFM_NS_REGION_PERIPH_1,
66  TFM_NS_REGION_PERIPH_2,
67  TFM_NS_SECONDARY_IMAGE_REGION,
68 };
69 
70 enum tfm_memory_access_e {
71  TFM_MEMORY_ACCESS_RO = 1,
72  TFM_MEMORY_ACCESS_RW = 2,
73 };
74 
75 extern int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share);
76 
77 extern int32_t tfm_core_validate_secure_caller(void);
78 
79 extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
80 
81 extern int32_t tfm_core_memory_permission_check(const void *ptr,
82  uint32_t size,
83  int32_t access);
84 
85 extern int32_t tfm_core_get_boot_data(uint8_t major_type,
86  struct tfm_boot_data *boot_data,
87  uint32_t len);
88 
89 int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);
90 
91 int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
92 
93 /**
94  * \brief Check whether the current partition has read access to a memory range
95  *
96  * This function assumes, that the current MPU configuration is set for the
97  * partition to be checked.
98  *
99  * \param[in] p The start address of the range to check
100  * \param[in] s The size of the range to check
101  * \param[in] ns_caller Whether the current partition is a non-secure one
102  * \param[in] privileged Privileged mode or unprivileged mode:
103  * \ref TFM_PARTITION_UNPRIVILEGED_MODE
104  * \ref TFM_PARTITION_PRIVILEGED_MODE
105  *
106  * \return TFM_SUCCESS if the partition has access to the memory range,
107  * TFM_ERROR_GENERIC otherwise.
108  */
109 int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
110  uint32_t ns_caller,
111  uint32_t privileged);
112 
113 /**
114  * \brief Check whether the current partition has write access to a memory range
115  *
116  * This function assumes, that the current MPU configuration is set for the
117  * partition to be checked.
118  *
119  * \param[in] p The start address of the range to check
120  * \param[in] s The size of the range to check
121  * \param[in] ns_caller Whether the current partition is a non-secure one
122  * \param[in] privileged Privileged mode or unprivileged mode:
123  * \ref TFM_PARTITION_UNPRIVILEGED_MODE
124  * \ref TFM_PARTITION_PRIVILEGED_MODE
125  *
126  * \return TFM_SUCCESS if the partition has access to the memory range,
127  * TFM_ERROR_GENERIC otherwise.
128  */
129 int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
130  uint32_t ns_caller,
131  uint32_t privileged);
132 
133 #ifdef TFM_PSA_API
134 /* The following macros are only valid if secure services can be called
135  * using veneer functions. This is not the case if IPC messaging is enabled
136  */
137 #define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
138  do { \
139  ERROR_MSG("Invalid TF-M configuration detected"); \
140  tfm_secure_api_error_handler(); \
141  /* This point never reached */ \
142  return (int32_t)TFM_ERROR_GENERIC; \
143  } while (0)
144 #define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
145  do { \
146  ERROR_MSG("Invalid TF-M configuration detected"); \
147  tfm_secure_api_error_handler(); \
148  /* This point never reached */ \
149  return (int32_t)TFM_ERROR_GENERIC; \
150  } while (0)
151 #else
152 #define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
153  return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
154  (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
155 
156 #define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
157  return tfm_core_partition_request(id, fn, TFM_SFN_API_LEGACY, \
158  (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
159 
160 __attribute__ ((always_inline)) __STATIC_INLINE
161 int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api,
162  int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
163 {
164  int32_t args[4] = {arg1, arg2, arg3, arg4};
165  struct tfm_sfn_req_s desc, *desc_ptr = &desc;
166 
167  desc.sp_id = id;
168  desc.sfn = (sfn_t) fn;
169  desc.args = args;
170  /*
171  * This preprocessor condition checks if a version of GCC smaller than
172  * 7.3.1 is being used to compile the code.
173  * These versions are affected by a bug on the cmse_nonsecure_caller
174  * intrinsic which returns incorrect results.
175  * Please check Bug 85203 on GCC Bugzilla for more information.
176  */
177 #if defined(__GNUC__) && !defined(__ARMCC_VERSION) && \
178  (__GNUC__ < 7 || \
179  (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || \
180  (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))))
181  /*
182  * Use the fact that, if called from Non-Secure, the LSB of the return
183  * address is set to 0.
184  */
185  desc.ns_caller = (uint32_t)!(
186  (intptr_t)__builtin_extract_return_addr(__builtin_return_address(0U))
187  & 1);
188 #else
189  /*
190  * Convert the result of cmse_nonsecure_caller from an int to a uint32_t
191  * to prevent using an int in the tfm_sfn_req_s structure.
192  */
193  desc.ns_caller = (cmse_nonsecure_caller() != 0) ? 1U : 0U;
194 #endif /* Check for GCC compiler version smaller than 7.3.1 */
195  desc.iovec_api = iovec_api;
196  if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
197  /* FixMe: Error severity TBD */
198  return TFM_ERROR_GENERIC;
199  } else {
200 #if TFM_LVL == 1
201  if (desc.ns_caller) {
202  return tfm_core_sfn_request(desc_ptr);
203  } else {
204  return tfm_core_sfn_request_thread_mode(desc_ptr);
205  }
206 #else
207  return tfm_core_sfn_request(desc_ptr);
208 #endif
209 
210  }
211 }
212 #endif
213 
214 #endif /* __TFM_SECURE_API_H__ */
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.