1 /*
2  * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "config_tfm.h"
9 #include "platform_sp.h"
10 
11 #include "tfm_platform_system.h"
12 #include "load/partition_defs.h"
13 #include "psa_manifest/pid.h"
14 
15 #if !PLATFORM_NV_COUNTER_MODULE_DISABLED
16 #include "tfm_plat_nv_counters.h"
17 #endif /* !PLATFORM_NV_COUNTER_MODULE_DISABLED */
18 
19 #include "psa/client.h"
20 #include "psa/service.h"
21 #include "region_defs.h"
22 #include "psa_manifest/tfm_platform.h"
23 
24 #if !PLATFORM_NV_COUNTER_MODULE_DISABLED
25 #define NV_COUNTER_ID_SIZE  sizeof(enum tfm_nv_counter_t)
26 #define NV_COUNTER_SIZE     4
27 #endif /* !PLATFORM_NV_COUNTER_MODULE_DISABLED */
28 
29 typedef enum tfm_platform_err_t (*plat_func_t)(const psa_msg_t *msg);
30 
31 enum tfm_platform_err_t platform_sp_system_reset(void)
32 {
33     /* FIXME: The system reset functionality is only supported in isolation
34      *        level 1.
35      */
36 
37     tfm_platform_hal_system_reset();
38 
39     return TFM_PLATFORM_ERR_SUCCESS;
40 }
41 
42 static psa_status_t platform_sp_system_reset_psa_api(const psa_msg_t *msg)
43 {
44     (void)msg; /* unused parameter */
45 
46     return platform_sp_system_reset();
47 }
48 
49 #if !PLATFORM_NV_COUNTER_MODULE_DISABLED
platform_sp_nv_read_psa_api(const psa_msg_t * msg)50 static psa_status_t platform_sp_nv_read_psa_api(const psa_msg_t *msg)
51 {
52     enum tfm_plat_err_t err = TFM_PLAT_ERR_SYSTEM_ERR;
53     size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, num = 0;
54 
55     enum tfm_nv_counter_t counter_id;
56     uint8_t counter_val[NV_COUNTER_SIZE] = {0};
57 
58     /* Check the number of in_vec filled */
59     while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
60         in_len--;
61     }
62 
63     /* Check the number of out_vec filled */
64     while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
65         out_len--;
66     }
67 
68     if ((msg->in_size[0] != NV_COUNTER_ID_SIZE) ||
69         (msg->out_size[0] > NV_COUNTER_SIZE) ||
70         (in_len != 1) || (out_len != 1)) {
71         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
72     }
73 
74     num = psa_read(msg->handle, 0, &counter_id, msg->in_size[0]);
75     if (num != NV_COUNTER_ID_SIZE) {
76         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
77     }
78 
79     if (msg->client_id < 0) {
80         err = tfm_plat_ns_counter_idx_to_nv_counter(counter_id, &counter_id);
81         if (err != TFM_PLAT_ERR_SUCCESS) {
82             return TFM_PLATFORM_ERR_INVALID_PARAM;
83         }
84     }
85 
86     err = tfm_plat_nv_counter_permissions_check(msg->client_id, counter_id, false);
87     if (err != TFM_PLAT_ERR_SUCCESS) {
88        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
89     }
90 
91     err = tfm_plat_read_nv_counter(counter_id,  msg->out_size[0],
92                                    counter_val);
93 
94     if (err != TFM_PLAT_ERR_SUCCESS) {
95        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
96     }
97 
98     psa_write(msg->handle, 0, counter_val, msg->out_size[0]);
99 
100     return TFM_PLATFORM_ERR_SUCCESS;
101 }
102 
platform_sp_nv_increment_psa_api(const psa_msg_t * msg)103 static psa_status_t platform_sp_nv_increment_psa_api(const psa_msg_t *msg)
104 {
105     enum tfm_plat_err_t err = TFM_PLAT_ERR_SYSTEM_ERR;
106     size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, num = 0;
107 
108     enum tfm_nv_counter_t counter_id;
109 
110     /* Check the number of in_vec filled */
111     while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
112         in_len--;
113     }
114 
115     /* Check the number of out_vec filled */
116     while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
117         out_len--;
118     }
119 
120     if ((msg->in_size[0] != NV_COUNTER_ID_SIZE) ||
121         (in_len != 1) || (out_len != 0)) {
122         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
123     }
124 
125     num = psa_read(msg->handle, 0, &counter_id, msg->in_size[0]);
126     if (num != NV_COUNTER_ID_SIZE) {
127         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
128     }
129 
130     if (msg->client_id < 0) {
131         err = tfm_plat_ns_counter_idx_to_nv_counter(counter_id, &counter_id);
132         if (err != TFM_PLAT_ERR_SUCCESS) {
133             return TFM_PLATFORM_ERR_INVALID_PARAM;
134         }
135     }
136 
137     err = tfm_plat_nv_counter_permissions_check(msg->client_id, counter_id, false);
138     if (err != TFM_PLAT_ERR_SUCCESS) {
139        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
140     }
141 
142     err = tfm_plat_increment_nv_counter(counter_id);
143 
144     if (err != TFM_PLAT_ERR_SUCCESS) {
145         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
146     }
147 
148     return TFM_PLATFORM_ERR_SUCCESS;
149 }
150 #endif /* !PLATFORM_NV_COUNTER_MODULE_DISABLED*/
151 
platform_sp_ioctl_psa_api(const psa_msg_t * msg)152 static psa_status_t platform_sp_ioctl_psa_api(const psa_msg_t *msg)
153 {
154     void *input = NULL;
155     void *output = NULL;
156     psa_invec invec = {0};
157     psa_outvec outvec = {0};
158     uint8_t input_buffer[PLATFORM_SERVICE_INPUT_BUFFER_SIZE] = {0};
159     uint8_t output_buffer[PLATFORM_SERVICE_OUTPUT_BUFFER_SIZE] = {0};
160     tfm_platform_ioctl_req_t request = 0;
161     enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SYSTEM_ERROR;
162     int num = 0;
163     uint32_t in_len = PSA_MAX_IOVEC;
164     uint32_t out_len = PSA_MAX_IOVEC;
165     size_t input_size;
166 
167     while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
168         in_len--;
169     }
170 
171     while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
172         out_len--;
173     }
174 
175     if ((in_len < 1) || (in_len > 2) ||
176         (out_len > 1)) {
177         return TFM_PLATFORM_ERR_SYSTEM_ERROR;
178     }
179 
180     num = psa_read(msg->handle, 0, &request, sizeof(request));
181     if (num != sizeof(request)) {
182         return (enum tfm_platform_err_t) PSA_ERROR_PROGRAMMER_ERROR;
183     }
184 
185     if (in_len > 1) {
186         input_size = msg->in_size[1];
187         if (input_size > PLATFORM_SERVICE_INPUT_BUFFER_SIZE) {
188             return (enum tfm_platform_err_t) PSA_ERROR_BUFFER_TOO_SMALL;
189         }
190         num = psa_read(msg->handle, 1, &input_buffer, msg->in_size[1]);
191         if (num != input_size) {
192             return (enum tfm_platform_err_t) PSA_ERROR_PROGRAMMER_ERROR;
193         }
194         invec.base = input_buffer;
195         invec.len = input_size;
196         input = &invec;
197     }
198 
199     if (out_len > 0) {
200         if (msg->out_size[0] > PLATFORM_SERVICE_OUTPUT_BUFFER_SIZE) {
201             return (enum tfm_platform_err_t) PSA_ERROR_PROGRAMMER_ERROR;
202         }
203         outvec.base = output_buffer;
204         outvec.len = msg->out_size[0];
205         output = &outvec;
206     }
207 
208     ret = tfm_platform_hal_ioctl(request, input, output);
209 
210     if (output != NULL) {
211         psa_write(msg->handle, 0, outvec.base, outvec.len);
212     }
213 
214     return ret;
215 }
216 
tfm_platform_service_sfn(const psa_msg_t * msg)217 psa_status_t tfm_platform_service_sfn(const psa_msg_t *msg)
218 {
219     switch (msg->type) {
220 #if !PLATFORM_NV_COUNTER_MODULE_DISABLED
221     case TFM_PLATFORM_API_ID_NV_READ:
222         return platform_sp_nv_read_psa_api(msg);
223     case TFM_PLATFORM_API_ID_NV_INCREMENT:
224         return platform_sp_nv_increment_psa_api(msg);
225 #endif /* PLATFORM_NV_COUNTER_MODULE_DISABLED */
226     case TFM_PLATFORM_API_ID_SYSTEM_RESET:
227         return platform_sp_system_reset_psa_api(msg);
228     case TFM_PLATFORM_API_ID_IOCTL:
229         return platform_sp_ioctl_psa_api(msg);
230     default:
231         return PSA_ERROR_NOT_SUPPORTED;
232     }
233 }
234 
platform_sp_init(void)235 psa_status_t platform_sp_init(void)
236 {
237 #if !PLATFORM_NV_COUNTER_MODULE_DISABLED
238     /* Initialise the non-volatile counters */
239     enum tfm_plat_err_t err;
240 
241     err = tfm_plat_init_nv_counter();
242     if (err != TFM_PLAT_ERR_SUCCESS) {
243         return PSA_ERROR_HARDWARE_FAILURE;
244     }
245 #endif /* PLATFORM_NV_COUNTER_MODULE_DISABLED */
246 
247     return PSA_SUCCESS;
248 }
249