TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_ipc_service_test.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdbool.h>
11 #include "psa/client.h"
12 #include "psa/service.h"
13 #include "tfm_secure_api.h"
14 #include "tfm_api.h"
16 
17 #define IPC_SERVICE_BUFFER_LEN 32
18 
19 /* Define the whether the service is inuse flag. */
20 static uint32_t service_in_use = 0;
21 
22 /* Define the global variable for the IPC_APP_ACCESS_PSA_MEM_SID service. */
25 
26 /*
27  * Fixme: Temporarily implement abort as infinite loop,
28  * will replace it later.
29  */
30 static void tfm_abort(void)
31 {
32  while (1)
33  ;
34 }
35 
36 static void ipc_service_basic(void)
37 {
38  psa_msg_t msg;
39  psa_status_t r;
40  int i;
41  uint8_t rec_buf[IPC_SERVICE_BUFFER_LEN];
42  uint8_t send_buf[IPC_SERVICE_BUFFER_LEN] = "It is just for IPC call test.";
43 
45  switch (msg.type) {
46  case PSA_IPC_CONNECT:
49  } else {
51  r = PSA_SUCCESS;
52  }
53  psa_reply(msg.handle, r);
54  break;
55  case PSA_IPC_CALL:
56  for (i = 0; i < PSA_MAX_IOVEC; i++) {
57  if (msg.in_size[i] != 0) {
58  psa_read(msg.handle, i, rec_buf, IPC_SERVICE_BUFFER_LEN);
59  }
60  if (msg.out_size[i] != 0) {
61  psa_write(msg.handle, i, send_buf, IPC_SERVICE_BUFFER_LEN);
62  }
63  }
65  break;
66  case PSA_IPC_DISCONNECT:
67  assert((service_in_use & IPC_SERVICE_TEST_BASIC_SIGNAL) != 0);
68  service_in_use &= ~IPC_SERVICE_TEST_BASIC_SIGNAL;
70  break;
71  default:
72  /* cannot get here? [broken SPM]. TODO*/
73  tfm_abort();
74  break;
75  }
76 }
77 
78 static void ipc_service_psa_access_app_mem(void)
79 {
80  psa_msg_t msg;
81  psa_status_t r;
82  char rec_data;
83  uint32_t rec_buf;
84 
86  switch (msg.type) {
87  case PSA_IPC_CONNECT:
90  } else {
92  r = PSA_SUCCESS;
93  }
94  psa_reply(msg.handle, r);
95  break;
96  case PSA_IPC_CALL:
97  /*
98  * rec_buf is a pointer pointed to a char type memory in client stack.
99  */
100  if (msg.in_size[0] != 0) {
101  psa_read(msg.handle, 0, &rec_buf, 4);
102  rec_data = *(char *)rec_buf;
103 
104  /* rec_data is assigned to 'A' by the client side. */
105  if (rec_data != 'A') {
106  psa_reply(msg.handle, -1);
107  break;
108  }
109 
110  /* Change the char type client stack memory to 'B'. */
111  *((char *)rec_buf) = 'B';
112  }
114  break;
115  case PSA_IPC_DISCONNECT:
116  assert((service_in_use & IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL)
117  != 0);
118  service_in_use &= ~IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL;
120  break;
121  default:
122  /* cannot get here? [broken SPM]. TODO*/
123  tfm_abort();
124  break;
125  }
126 }
127 
128 #ifdef TFM_IPC_ISOLATION_2_TEST_READ_ONLY_MEM
129 static void ipc_service_psa_access_app_readonly_mem(void)
130 {
131  psa_msg_t msg;
132  psa_status_t r;
133  char rec_data;
134  uint32_t rec_buf;
135 
137  switch (msg.type) {
138  case PSA_IPC_CONNECT:
139  if (service_in_use &
142  } else {
143  service_in_use |=
145  r = PSA_SUCCESS;
146  }
147  psa_reply(msg.handle, r);
148  break;
149  case PSA_IPC_CALL:
150  /*
151  * rec_buf is a pointer pointed to a char type memory in client
152  * code section. Write the memory will cause MemManage fault.
153  */
154  if (msg.in_size[0] != 0) {
155  psa_read(msg.handle, 0, &rec_buf, 4);
156  rec_data = *(char *)rec_buf;
157 
158  /* rec_data is assigned to 'A' by the client side. */
159  if (rec_data != 'A') {
160  psa_reply(msg.handle, -1);
161  break;
162  }
163 
164  /* Write the char type read only memory. */
165  *((char *)rec_buf) = 'B';
166  }
167 
169  break;
170  case PSA_IPC_DISCONNECT:
171  assert((service_in_use &
172  IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL) != 0);
173  service_in_use &=
174  ~IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL;
176  break;
177  default:
178  /* cannot get here? [broken SPM]. TODO*/
179  tfm_abort();
180  break;
181  }
182 }
183 #endif
184 
185 #if defined TFM_IPC_ISOLATION_2_MEM_CHECK \
186  || defined TFM_IPC_ISOLATION_2_APP_ACCESS_PSA_MEM
187 static void ipc_service_app_access_psa_mem(void)
188 {
189  psa_msg_t msg;
190  psa_status_t r;
191 
193  switch (msg.type) {
194  case PSA_IPC_CONNECT:
197  } else {
199  r = PSA_SUCCESS;
200  }
201 
202  psa_reply(msg.handle, r);
203  break;
204  case PSA_IPC_CALL:
205  if (msg.out_size[0] != 0) {
206 
207  /*
208  * Write a pointer to outvec. The pointer points to uint8_t
209  * memory in ipc servive partition.
210  */
212  sizeof(ipc_service_data_p));
213  }
214 
216  break;
217  case PSA_IPC_DISCONNECT:
218  assert((service_in_use & IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL)
219  != 0);
220  service_in_use &= ~IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL;
222  break;
223  default:
224  /* cannot get here? [broken SPM]. TODO*/
225  tfm_abort();
226  break;
227  }
228 }
229 #endif
230 
231 static void ipc_service_programmer_error(void)
232 {
233  psa_msg_t msg;
234  psa_status_t r;
235 
237  switch (msg.type) {
238  case PSA_IPC_CONNECT:
241  } else {
243  r = PSA_SUCCESS;
244  }
245  psa_reply(msg.handle, r);
246  break;
247  case PSA_IPC_CALL:
249  break;
250  case PSA_IPC_DISCONNECT:
251  assert((service_in_use
252  & IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SIGNAL) != 0);
253  service_in_use &= ~IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SIGNAL;
255  break;
256  default:
257  /* cannot get here? [broken SPM]. TODO*/
258  tfm_abort();
259  break;
260  }
261 }
262 
263 /* Test thread */
264 void ipc_service_test_main(void *param)
265 {
266  uint32_t signals = 0;
267 
268  while (1) {
269  signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
270  if (signals & IPC_SERVICE_TEST_BASIC_SIGNAL) {
271  ipc_service_basic();
272  } else if (signals & IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL) {
273  ipc_service_psa_access_app_mem();
274 #ifdef TFM_IPC_ISOLATION_2_TEST_READ_ONLY_MEM
275  } else if (signals
276  & IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL) {
277  ipc_service_psa_access_app_readonly_mem();
278 #endif
279 #if defined TFM_IPC_ISOLATION_2_MEM_CHECK \
280  || defined TFM_IPC_ISOLATION_2_APP_ACCESS_PSA_MEM
281  } else if (signals & IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL) {
282  ipc_service_app_access_psa_mem();
283 #endif
285  ipc_service_programmer_error();
286  } else {
287  /* Should not come here */
288  tfm_abort();
289  }
290  }
291 }
#define PSA_BLOCK
Definition: service.h:31
int32_t type
Definition: service.h:56
#define PSA_SUCCESS
Definition: crypto_values.h:35
#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL
#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buffer, size_t num_bytes)
Read a message parameter or part of a message parameter from a client input vector.
Definition: psa_service.c:40
psa_handle_t handle
Definition: service.h:61
#define PSA_MAX_IOVEC
Definition: client.h:54
#define PSA_IPC_DISCONNECT
Definition: service.h:47
void ipc_service_test_main(void *param)
#define PSA_ERROR_PROGRAMMER_ERROR
Definition: error.h:32
#define PSA_WAIT_ANY
Definition: service.h:36
uint32_t service_in_use
uint8_t * ipc_service_data_p
size_t in_size[PSA_MAX_IOVEC]
Definition: service.h:70
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes)
Write a message response to a client output vector.
Definition: psa_service.c:58
void psa_reply(psa_handle_t msg_handle, psa_status_t status)
Complete handling of a specific message and unblock the client.
Definition: psa_service.c:67
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
Return the Secure Partition interrupt signals that have been asserted from a subset of signals provid...
Definition: psa_service.c:15
uint8_t ipc_servic_data
#define PSA_ERROR_CONNECTION_REFUSED
Definition: error.h:33
#define PSA_IPC_CONNECT
Definition: service.h:45
#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL
size_t out_size[PSA_MAX_IOVEC]
Definition: service.h:73
#define PSA_IPC_CALL
Definition: client.h:59
#define IPC_SERVICE_TEST_BASIC_SIGNAL
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
Retrieve the message which corresponds to a given RoT Service signal and remove the message from the ...
Definition: psa_service.c:24
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:43
#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SIGNAL
#define IPC_SERVICE_BUFFER_LEN