1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4 */
5
6 #include <stdbool.h>
7
8 #include "async.h"
9 #include "config_impl.h"
10 #include "ns_agent_mailbox_rpc.h"
11 #include "spm.h"
12 #include "tfm_log_unpriv.h"
13 #include "tfm_rpc.h"
14
default_handle_req(void)15 static void default_handle_req(void)
16 {
17 psa_panic();
18 }
19
default_mailbox_reply(const void * owner,int32_t ret)20 static void default_mailbox_reply(const void *owner, int32_t ret)
21 {
22 (void)owner;
23 (void)ret;
24
25 psa_panic();
26 }
27
default_handle_req_irq_src(uint32_t irq_src)28 static void default_handle_req_irq_src(uint32_t irq_src)
29 {
30 (void)irq_src;
31
32 psa_panic();
33 }
34
default_process_new_msg(uint32_t * nr_msg)35 static int32_t default_process_new_msg(uint32_t *nr_msg)
36 {
37 return PSA_SUCCESS;
38 }
39
40 static struct tfm_rpc_ops_t rpc_ops = {
41 .handle_req = default_handle_req,
42 .reply = default_mailbox_reply,
43 .handle_req_irq_src = default_handle_req_irq_src,
44 .process_new_msg = default_process_new_msg,
45 };
46
tfm_rpc_register_ops(const struct tfm_rpc_ops_t * ops_ptr)47 int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr)
48 {
49 if (ops_ptr == NULL) {
50 return TFM_RPC_INVAL_PARAM;
51 }
52
53 if ((ops_ptr->handle_req == NULL) || (ops_ptr->reply == NULL)) {
54 return TFM_RPC_INVAL_PARAM;
55 }
56
57 /* Currently, one and only one RPC callback instance is supported. */
58 if ((rpc_ops.handle_req != default_handle_req) ||
59 (rpc_ops.reply != default_mailbox_reply)) {
60 return TFM_RPC_CONFLICT_CALLBACK;
61 }
62
63 rpc_ops.handle_req = ops_ptr->handle_req;
64 rpc_ops.reply = ops_ptr->reply;
65 rpc_ops.handle_req_irq_src = default_handle_req_irq_src;
66 if (ops_ptr->process_new_msg != NULL) {
67 rpc_ops.process_new_msg = ops_ptr->process_new_msg;
68 }
69
70 return TFM_RPC_SUCCESS;
71 }
72
tfm_rpc_register_ops_multi_srcs(const struct tfm_rpc_ops_t * ops_ptr)73 int32_t tfm_rpc_register_ops_multi_srcs(const struct tfm_rpc_ops_t *ops_ptr)
74 {
75 if (ops_ptr == NULL) {
76 return TFM_RPC_INVAL_PARAM;
77 }
78
79 if ((ops_ptr->handle_req_irq_src == NULL) || (ops_ptr->reply == NULL)) {
80 return TFM_RPC_INVAL_PARAM;
81 }
82
83 /* Currently, one and only one RPC callback instance is supported. */
84 if ((rpc_ops.handle_req_irq_src != default_handle_req_irq_src) ||
85 (rpc_ops.reply != default_mailbox_reply)) {
86 return TFM_RPC_CONFLICT_CALLBACK;
87 }
88
89 rpc_ops.handle_req = default_handle_req;
90 rpc_ops.reply = ops_ptr->reply;
91 rpc_ops.handle_req_irq_src = ops_ptr->handle_req_irq_src;
92 if (ops_ptr->process_new_msg != NULL) {
93 rpc_ops.process_new_msg = ops_ptr->process_new_msg;
94 }
95
96 return TFM_RPC_SUCCESS;
97 }
98
tfm_rpc_unregister_ops(void)99 void tfm_rpc_unregister_ops(void)
100 {
101 rpc_ops.handle_req = default_handle_req;
102 rpc_ops.reply = default_mailbox_reply;
103 rpc_ops.handle_req_irq_src = default_handle_req_irq_src;
104 rpc_ops.process_new_msg = default_process_new_msg;
105 }
106
tfm_rpc_client_call_handler(psa_signal_t signal)107 void tfm_rpc_client_call_handler(psa_signal_t signal)
108 {
109 uint32_t irq_src;
110
111 if (rpc_ops.handle_req_irq_src != default_handle_req_irq_src) {
112 irq_src = rpc_map_signal_to_irq(signal);
113 if (irq_src == INVALID_MAILBOX_IRQ) {
114 psa_panic();
115 }
116
117 rpc_ops.handle_req_irq_src(irq_src);
118 return;
119 }
120
121 rpc_ops.handle_req();
122 }
123
124 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
tfm_rpc_client_call_reply(void)125 void tfm_rpc_client_call_reply(void)
126 {
127 psa_msg_t msg;
128 struct connection_t *handle;
129 psa_status_t status;
130
131 status = psa_get(ASYNC_MSG_REPLY, &msg);
132 if (status != PSA_SUCCESS) {
133 ERROR_UNPRIV("psa_get(ASYNC_MSG_REPLY) call returned %d\n", status);
134 return;
135 }
136
137 handle = (struct connection_t *)msg.rhandle;
138
139 rpc_ops.reply(handle->client_data, handle->replied_value);
140
141 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
142 spm_free_connection(handle);
143 } else {
144 handle->status = TFM_HANDLE_STATUS_IDLE;
145 }
146 }
147 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
148
tfm_rpc_client_process_new_msg(uint32_t * nr_msg)149 int32_t tfm_rpc_client_process_new_msg(uint32_t *nr_msg)
150 {
151 return rpc_ops.process_new_msg(nr_msg);
152 }
153