blob: 23e450eb0a2c27717e1fba82be693e88db018c99 [file] [log] [blame]
David Hud2753b32019-09-23 18:46:15 +08001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <string.h>
9#include "tfm_ns_mailbox.h"
10
11/* The pointer to NSPE mailbox queue */
12static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL;
13
14static inline void clear_queue_slot_empty(uint8_t idx)
15{
16 if (idx < NUM_MAILBOX_QUEUE_SLOT) {
17 mailbox_queue_ptr->empty_slots &= ~(1 << idx);
18 }
19}
20
21static inline void set_queue_slot_empty(uint8_t idx)
22{
23 if (idx < NUM_MAILBOX_QUEUE_SLOT) {
24 mailbox_queue_ptr->empty_slots |= (1 << idx);
25 }
26}
27
28static inline void set_queue_slot_pend(uint8_t idx)
29{
30 if (idx < NUM_MAILBOX_QUEUE_SLOT) {
31 mailbox_queue_ptr->pend_slots |= (1 << idx);
32 }
33}
34
35static inline int32_t get_mailbox_msg_handle(uint8_t idx,
36 mailbox_msg_handle_t *handle)
37{
38 if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) {
39 return MAILBOX_INVAL_PARAMS;
40 }
41
42 *handle = (mailbox_msg_handle_t)(idx + 1);
43
44 return MAILBOX_SUCCESS;
45}
46
47static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle,
48 uint8_t *idx)
49{
50 if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) {
51 return MAILBOX_INVAL_PARAMS;
52 }
53
54 *idx = (uint8_t)(handle - 1);
55
56 return MAILBOX_SUCCESS;
57}
58
59static inline void clear_queue_slot_replied(uint8_t idx)
60{
61 if (idx < NUM_MAILBOX_QUEUE_SLOT) {
62 mailbox_queue_ptr->replied_slots &= ~(1 << idx);
63 }
64}
65
66static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue)
67{
68 uint8_t idx;
69 mailbox_queue_status_t status;
70
71 tfm_ns_mailbox_hal_enter_critical();
72 status = queue->empty_slots;
73
74 if (!status) {
75 /* No empty slot */
76 tfm_ns_mailbox_hal_exit_critical();
77 return NUM_MAILBOX_QUEUE_SLOT;
78 }
79
80 for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) {
81 if (status & (1 << idx)) {
82 break;
83 }
84 }
85
86 clear_queue_slot_empty(idx);
87
88 tfm_ns_mailbox_hal_exit_critical();
89
90 return idx;
91}
92
93mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type,
94 const struct psa_client_params_t *params,
95 int32_t client_id)
96{
97 uint8_t idx;
98 struct mailbox_msg_t *msg_ptr;
99 mailbox_msg_handle_t handle;
100
101 if (!mailbox_queue_ptr) {
102 return MAILBOX_MSG_NULL_HANDLE;
103 }
104
105 if (!params) {
106 return MAILBOX_MSG_NULL_HANDLE;
107 }
108
109 idx = acquire_empty_slot(mailbox_queue_ptr);
110 if (idx >= NUM_MAILBOX_QUEUE_SLOT) {
111 return MAILBOX_QUEUE_FULL;
112 }
113
114 /* Fill the mailbox message */
115 msg_ptr = &mailbox_queue_ptr->queue[idx].msg;
116
117 msg_ptr->call_type = call_type;
118 memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params));
119 msg_ptr->client_id = client_id;
120
121 get_mailbox_msg_handle(idx, &handle);
122
123 tfm_ns_mailbox_hal_enter_critical();
124 set_queue_slot_pend(idx);
125 tfm_ns_mailbox_hal_exit_critical();
126
127 tfm_ns_mailbox_hal_notify_peer();
128
129 return handle;
130}
131
132int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle,
133 int32_t *reply)
134{
135 uint8_t idx;
136 int32_t ret;
137
138 if (!mailbox_queue_ptr) {
139 return MAILBOX_INVAL_PARAMS;
140 }
141
142 if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) {
143 return MAILBOX_INVAL_PARAMS;
144 }
145
146 ret = get_mailbox_msg_idx(handle, &idx);
147 if (ret != MAILBOX_SUCCESS) {
148 return ret;
149 }
150
151 *reply = mailbox_queue_ptr->queue[idx].reply.return_val;
152
153 tfm_ns_mailbox_hal_enter_critical();
154 set_queue_slot_empty(idx);
155 clear_queue_slot_replied(idx);
156 tfm_ns_mailbox_hal_exit_critical();
157
158 return MAILBOX_SUCCESS;
159}
160
161bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle)
162{
163 uint8_t idx;
164 int32_t ret;
165 mailbox_queue_status_t status;
166
167 if (!mailbox_queue_ptr) {
168 return false;
169 }
170
171 if (handle == MAILBOX_MSG_NULL_HANDLE) {
172 return false;
173 }
174
175 ret = get_mailbox_msg_idx(handle, &idx);
176 if (ret != MAILBOX_SUCCESS) {
177 return false;
178 }
179
180 tfm_ns_mailbox_hal_enter_critical();
181 status = mailbox_queue_ptr->replied_slots;
182 tfm_ns_mailbox_hal_exit_critical();
183
184 if (status & (1 << idx)) {
185 return true;
186 }
187
188 return false;
189}
190
191int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue)
192{
193 int32_t ret;
194
195 if (!queue) {
196 return MAILBOX_INVAL_PARAMS;
197 }
198
199 /*
200 * Further verification of mailbox queue address may be required according
201 * to non-secure memory assignment.
202 */
203
204 memset(queue, 0, sizeof(*queue));
205
206 /* Initialize empty bitmask */
207 queue->empty_slots = (mailbox_queue_status_t)((1 << NUM_MAILBOX_QUEUE_SLOT)
208 - 1);
209
210 mailbox_queue_ptr = queue;
211
212 /* Platform specific initialization. */
213 ret = tfm_ns_mailbox_hal_init(queue);
214
215 return ret;
216}