1 /*
2  * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "compiler_ext_defs.h"
9 #include "internal_status_code.h"
10 #include "spm.h"
11 #include "tfm_arch.h"
12 
13 #ifdef CONFIG_TFM_CONN_HANDLE_MAX_NUM
14 #pragma message("CONFIG_TFM_CONN_HANDLE_MAX_NUM is not used in SFN model without connection-based services.")
15 #endif
16 
17 /*
18  * Bits [2:0] of PSPLIM are reserved in v8m,
19  * so PSPLIM has to be 8 bytes aligned when allocating space for connection.
20  */
21 #define CONNECTION_SIZE        ((sizeof(struct connection_t) + 7) & ~0x7)
22 #define FIXED_STATIC_HANDLE    ((psa_handle_t)0x1000)
23 
alloc_conn_from_stack_top(void)24 static inline struct connection_t *alloc_conn_from_stack_top(void)
25 {
26     uint32_t stack_top = tfm_arch_get_psplim();
27 
28     tfm_arch_set_psplim(stack_top + CONNECTION_SIZE);
29 
30     return (struct connection_t *)stack_top;
31 }
32 
free_conn_from_stack_top(void)33 static inline void free_conn_from_stack_top(void)
34 {
35     uint32_t stack_top = tfm_arch_get_psplim();
36 
37     tfm_arch_set_psplim(stack_top - CONNECTION_SIZE);
38 }
39 
40 /*********************** Connection handle conversion APIs *******************/
41 
42 /*
43  * A connection instance connection_t allocated inside SPM is actually a memory
44  * address in PSP stack. Return this connection to the client directly
45  * exposes information of secure memory address. In this case, converting the
46  * connection into another handle value does not represent the memory address
47  * to avoid exposing secure memory directly to clients.
48  * Since the current connection can always be calculated from the address of
49  * PSP stack top, it is good enough to return a fixed static handle value to client.
50  */
connection_to_handle(struct connection_t * p_connection)51 psa_handle_t connection_to_handle(struct connection_t *p_connection)
52 {
53     (void)p_connection;
54 
55     return FIXED_STATIC_HANDLE;
56 }
57 
handle_to_connection(psa_handle_t handle)58 struct connection_t *handle_to_connection(psa_handle_t handle)
59 {
60     struct connection_t *p_connection;
61 
62     if (handle != FIXED_STATIC_HANDLE) {
63         return NULL;
64     }
65 
66     p_connection = (struct connection_t *)
67                    (tfm_arch_get_psplim() - CONNECTION_SIZE);
68 
69     return p_connection;
70 }
71 
72 /* Service handle management functions */
spm_init_connection_space(void)73 void spm_init_connection_space(void)
74 {
75     /*
76      * No initialization is required for local handle,
77      * because space for connection will be directly allocated
78      * from stack when calling spm_allocate_connection.
79      */
80 }
81 
spm_allocate_connection(void)82 struct connection_t *spm_allocate_connection(void)
83 {
84     return alloc_conn_from_stack_top();
85 }
86 
spm_validate_connection(const struct connection_t * p_connection)87 psa_status_t spm_validate_connection(const struct connection_t *p_connection)
88 {
89     /* Connection address is always calculated from PSPLIM. No need to validate here. */
90     return PSA_SUCCESS;
91 }
92 
spm_free_connection(struct connection_t * p_connection)93 void spm_free_connection(struct connection_t *p_connection)
94 {
95     (void)p_connection;
96 
97     free_conn_from_stack_top();
98 }
99