aboutsummaryrefslogtreecommitdiff
path: root/secure_fw/core/tfm_secure_api.h
blob: 69828f069314f038d897b05c7b91a8f58fe4caf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#ifndef __TFM_SECURE_API_H__
#define __TFM_SECURE_API_H__

#include <arm_cmse.h>
#include "tfm_arch.h"
#include "tfm_svc.h"
#include "tfm_core.h"
#include "tfm_api.h"
#include "bl2/include/tfm_boot_status.h"
#include "psa/service.h"

/*!
 * \def __tfm_secure_gateway_attributes__
 *
 * \brief Attributes for secure gateway functions
 */
#define __tfm_secure_gateway_attributes__ \
        __attribute__((cmse_nonsecure_entry, noinline, section("SFN")))

/* Hide specific errors if not debugging */
#ifdef TFM_CORE_DEBUG
#define TFM_ERROR_STATUS(status) (status)
#else
#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
#endif

#define TFM_SFN_API_LEGACY 0
#define TFM_SFN_API_IOVEC 1

#ifndef TFM_LVL
#error TFM_LVL is not defined!
#endif

extern void tfm_secure_api_error_handler(void);

typedef int32_t(*sfn_t)(int32_t, int32_t, int32_t, int32_t);

struct tfm_sfn_req_s {
    uint32_t sp_id;
    sfn_t sfn;
    int32_t *args;
    uint32_t caller_part_idx;
    int32_t iovec_api;
    uint32_t ns_caller;
};

#define TFM_BUFFER_SHARE_DISABLE 0U
#define TFM_BUFFER_SHARE_NS_CODE 1U
#define TFM_BUFFER_SHARE_SCRATCH 2U
/* only for TCB in level 2, all in level 1 */
#define TFM_BUFFER_SHARE_PRIV    3U
#define TFM_BUFFER_SHARE_DEFAULT 4U

enum tfm_ns_region_e {
    TFM_NS_REGION_CODE = 0,
    TFM_NS_REGION_DATA,
    TFM_NS_REGION_VENEER,
    TFM_NS_REGION_PERIPH_1,
    TFM_NS_REGION_PERIPH_2,
    TFM_NS_SECONDARY_IMAGE_REGION,
};

enum tfm_memory_access_e {
    TFM_MEMORY_ACCESS_RO = 1,
    TFM_MEMORY_ACCESS_RW = 2,
};

extern int32_t tfm_core_set_buffer_area(uint32_t share);

extern int32_t tfm_core_validate_secure_caller(void);

extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);

extern int32_t tfm_core_memory_permission_check(const void *ptr,
                                                uint32_t size,
                                                int32_t access);

extern int32_t tfm_core_get_boot_data(uint8_t major_type,
                                      struct tfm_boot_data *boot_data,
                                      uint32_t len);

int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);

int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);

/**
 * \brief Check whether the current partition has read access to a memory range
 *
 * This function assumes, that the current MPU configuration is set for the
 * partition to be checked.
 *
 * \param[in] p                The start address of the range to check
 * \param[in] s                The size of the range to check
 * \param[in] ns_caller        Whether the current partition is a non-secure one
 * \param[in] privileged       Privileged mode or unprivileged mode:
 *                             \ref TFM_PARTITION_UNPRIVILEGED_MODE
 *                             \ref TFM_PARTITION_PRIVILEGED_MODE
 *
 * \return TFM_SUCCESS if the partition has access to the memory range,
 *         TFM_ERROR_GENERIC otherwise.
 */
enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
                                                     uint32_t ns_caller,
                                                     uint32_t privileged);

/**
 * \brief Check whether the current partition has write access to a memory range
 *
 * This function assumes, that the current MPU configuration is set for the
 * partition to be checked.
 *
 * \param[in] p                The start address of the range to check
 * \param[in] s                The size of the range to check
 * \param[in] ns_caller        Whether the current partition is a non-secure one
 * \param[in] privileged       Privileged mode or unprivileged mode:
 *                             \ref TFM_PARTITION_UNPRIVILEGED_MODE
 *                             \ref TFM_PARTITION_PRIVILEGED_MODE
 *
 * \return TFM_SUCCESS if the partition has access to the memory range,
 *         TFM_ERROR_GENERIC otherwise.
 */
enum tfm_status_e tfm_core_has_write_access_to_region(void *p, size_t s,
                                                      uint32_t ns_caller,
                                                      uint32_t privileged);

void tfm_enable_irq(psa_signal_t irq_signal);
void tfm_disable_irq(psa_signal_t irq_signal);

#ifdef TFM_PSA_API
/* The following macros are only valid if secure services can be called
 * using veneer functions. This is not the case if IPC messaging is enabled
 */
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d)               \
        do {                                                         \
            ERROR_MSG("Invalid TF-M configuration detected");        \
            tfm_secure_api_error_handler();                          \
            /* This point never reached */                           \
            return (int32_t)TFM_ERROR_GENERIC;                       \
        } while (0)
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d)                     \
        do {                                                         \
            ERROR_MSG("Invalid TF-M configuration detected");        \
            tfm_secure_api_error_handler();                          \
            /* This point never reached */                           \
            return (int32_t)TFM_ERROR_GENERIC;                       \
        } while (0)
#else
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
        return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
                (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)

#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
        return tfm_core_partition_request(id, fn, TFM_SFN_API_LEGACY, \
                (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)

__attribute__ ((always_inline)) __STATIC_INLINE
int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api,
            int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
{
    int32_t args[4] = {arg1, arg2, arg3, arg4};
    struct tfm_sfn_req_s desc, *desc_ptr = &desc;

    desc.sp_id = id;
    desc.sfn = (sfn_t) fn;
    desc.args = args;
    /*
     * This preprocessor condition checks if a version of GCC smaller than
     * 7.3.1 is being used to compile the code.
     * These versions are affected by a bug on the cmse_nonsecure_caller
     * intrinsic which returns incorrect results.
     * Please check Bug 85203 on GCC Bugzilla for more information.
     */
#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && \
    (__GNUC__ < 7 || \
     (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || \
                       (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))))
    /*
     * Use the fact that, if called from Non-Secure, the LSB of the return
     * address is set to 0.
     */
    desc.ns_caller = (uint32_t)!(
           (intptr_t)__builtin_extract_return_addr(__builtin_return_address(0U))
           & 1);
#else
    /*
     * Convert the result of cmse_nonsecure_caller from an int to a uint32_t
     * to prevent using an int in the tfm_sfn_req_s structure.
     */
    desc.ns_caller = (cmse_nonsecure_caller() != 0) ? 1U : 0U;
#endif /* Check for GCC compiler version smaller than 7.3.1 */
    desc.iovec_api = iovec_api;
    if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
        /* FixMe: Error severity TBD */
        return (int32_t)TFM_ERROR_GENERIC;
    } else {
        if (desc.ns_caller) {
            return tfm_core_sfn_request(desc_ptr);
        } else {
            return tfm_core_sfn_request_thread_mode(desc_ptr);
        }
    }
}
#endif

#endif /* __TFM_SECURE_API_H__ */