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