1 #include "openamp/open_amp.h"
2 #include "openamp/rpmsg_retarget.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <fcntl.h>
7 /*************************************************************************
8 * Description
9 * This files contains rpmsg based redefinitions for C RTL system calls
10 * such as _open, _read, _write, _close.
11 *************************************************************************/
12 static struct _rpc_data *rpc_data;
13 static unsigned int rpc_data_synclock = 0;
14 int get_response = 0;
16 int send_rpc(void *data, int len);
17 static int rpc_count = 0;
19 void rpc_cb(struct rpmsg_channel *rtl_rp_chnl, void *data, int len, void *priv,
20 unsigned long src)
21 {
22 memcpy(rpc_data->rpc_response, data, len);
23 env_release_sync_lock(rpc_data->sync_lock);
24 get_response = 1;
26 if (rpc_data->rpc_response->id == TERM_SYSCALL_ID) {
27 /* Application terminate signal is received from the proxy app,
28 * so let the application know of terminate message.
29 */
30 rpc_data->shutdown_cb(rtl_rp_chnl);
31 }
32 }
34 int send_rpc(void *data, int len)
35 {
36 int retval;
38 retval = rpmsg_sendto(rpc_data->rpmsg_chnl, data, len, PROXY_ENDPOINT);
39 return retval;
40 }
42 int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb)
43 {
44 int status;
46 /* Allocate memory for rpc control block */
47 rpc_data =
48 (struct _rpc_data *)env_allocate_memory(sizeof(struct _rpc_data));
50 /* Create a mutex for synchronization */
51 status = env_create_mutex(&rpc_data->rpc_lock, 1);
53 /* Create a mutex for synchronization */
54 status = env_create_sync_lock(&rpc_data->sync_lock, LOCKED);
56 /* Create a endpoint to handle rpc response from master */
57 rpc_data->rpmsg_chnl = rp_chnl;
58 rpc_data->rp_ept = rpmsg_create_ept(rpc_data->rpmsg_chnl, rpc_cb,
59 RPMSG_NULL, PROXY_ENDPOINT);
60 rpc_data->rpc = env_allocate_memory(RPC_BUFF_SIZE);
61 rpc_data->rpc_response = env_allocate_memory(RPC_BUFF_SIZE);
62 rpc_data->shutdown_cb = cb;
64 return status;
65 }
67 int rpmsg_retarget_deinit(struct rpmsg_channel *rp_chnl)
68 {
69 env_free_memory(rpc_data->rpc);
70 env_free_memory(rpc_data->rpc_response);
71 env_delete_mutex(rpc_data->rpc_lock);
72 env_delete_sync_lock(rpc_data->sync_lock);
73 rpmsg_destroy_ept(rpc_data->rp_ept);
74 env_free_memory(rpc_data);
76 return 0;
77 }
79 int rpmsg_retarget_send(void *data, int len)
80 {
81 return send_rpc(data, len);
82 }
84 /*************************************************************************
85 *
86 * FUNCTION
87 *
88 * _open
89 *
90 * DESCRIPTION
91 *
92 * Open a file. Minimal implementation
93 *
94 *************************************************************************/
95 int _open(const char *filename, int flags, int mode)
96 {
97 int filename_len = strlen(filename) + 1;
98 int payload_size = sizeof(struct _sys_rpc) + filename_len;
99 int retval = -1;
101 if ((!filename) || (filename_len > FILE_NAME_LEN)) {
102 return -1;
103 }
105 /* Construct rpc payload */
106 rpc_data->rpc->id = OPEN_SYSCALL_ID;
107 rpc_data->rpc->sys_call_args.int_field1 = flags;
108 rpc_data->rpc->sys_call_args.int_field2 = mode;
109 rpc_data->rpc->sys_call_args.data_len = filename_len;
110 memcpy(&rpc_data->rpc->sys_call_args.data, filename, filename_len);
112 /* Transmit rpc request */
113 env_lock_mutex(rpc_data->rpc_lock);
114 send_rpc((void *)rpc_data->rpc, payload_size);
115 env_unlock_mutex(rpc_data->rpc_lock);
117 /* Wait for response from proxy on master */
118 env_acquire_sync_lock(rpc_data->sync_lock);
120 /* Obtain return args and return to caller */
121 if (rpc_data->rpc_response->id == OPEN_SYSCALL_ID) {
122 retval = rpc_data->rpc_response->sys_call_args.int_field1;
123 }
125 return retval;
126 }
128 /*************************************************************************
129 *
130 * FUNCTION
131 *
132 * _read
133 *
134 * DESCRIPTION
135 *
136 * Low level function to redirect IO to serial.
137 *
138 *************************************************************************/
139 int _read(int fd, char *buffer, int buflen)
140 {
141 int payload_size = sizeof(struct _sys_rpc);
142 int retval = -1;
144 if (!buffer || !buflen)
145 return retval;
147 /* Construct rpc payload */
148 rpc_data->rpc->id = READ_SYSCALL_ID;
149 rpc_data->rpc->sys_call_args.int_field1 = fd;
150 rpc_data->rpc->sys_call_args.int_field2 = buflen;
151 rpc_data->rpc->sys_call_args.data_len = 0; /*not used */
153 /* Transmit rpc request */
154 env_lock_mutex(rpc_data->rpc_lock);
155 get_response = 0;
156 send_rpc((void *)rpc_data->rpc, payload_size);
157 env_unlock_mutex(rpc_data->rpc_lock);
159 /* Wait for response from proxy on master */
160 env_acquire_sync_lock(rpc_data->sync_lock);
162 /* Obtain return args and return to caller */
163 if (rpc_data->rpc_response->id == READ_SYSCALL_ID) {
164 if (rpc_data->rpc_response->sys_call_args.int_field1 > 0) {
165 memcpy(buffer,
166 rpc_data->rpc_response->sys_call_args.data,
167 rpc_data->rpc_response->sys_call_args.data_len);
168 }
170 retval = rpc_data->rpc_response->sys_call_args.int_field1;
171 }
173 return retval;
174 }
176 /*************************************************************************
177 *
178 * FUNCTION
179 *
180 * _write
181 *
182 * DESCRIPTION
183 *
184 * Low level function to redirect IO to serial.
185 *
186 *************************************************************************/
187 int _write(int fd, const char *ptr, int len)
188 {
189 int retval = -1;
190 int payload_size = sizeof(struct _sys_rpc) + len;
191 int null_term = 0;
193 if (fd == 1) {
194 null_term = 1;
195 }
197 rpc_data->rpc->id = WRITE_SYSCALL_ID;
198 rpc_data->rpc->sys_call_args.int_field1 = fd;
199 rpc_data->rpc->sys_call_args.int_field2 = len;
200 rpc_data->rpc->sys_call_args.data_len = len + null_term;
201 memcpy(rpc_data->rpc->sys_call_args.data, ptr, len);
202 if (null_term) {
203 *(char *)(rpc_data->rpc->sys_call_args.data + len + null_term) =
204 0;
205 }
207 env_lock_mutex(rpc_data->rpc_lock);
208 send_rpc((void *)rpc_data->rpc, payload_size);
209 env_unlock_mutex(rpc_data->rpc_lock);
211 env_acquire_sync_lock(rpc_data->sync_lock);
213 if (rpc_data->rpc_response->id == WRITE_SYSCALL_ID) {
214 retval = rpc_data->rpc_response->sys_call_args.int_field1;
215 }
217 return retval;
219 }
221 /*************************************************************************
222 *
223 * FUNCTION
224 *
225 * _close
226 *
227 * DESCRIPTION
228 *
229 * Close a file. Minimal implementation
230 *
231 *************************************************************************/
232 int _close(int fd)
233 {
234 int payload_size = sizeof(struct _sys_rpc);
235 int retval = -1;
237 rpc_data->rpc->id = CLOSE_SYSCALL_ID;
238 rpc_data->rpc->sys_call_args.int_field1 = fd;
239 rpc_data->rpc->sys_call_args.int_field2 = 0; /*not used */
240 rpc_data->rpc->sys_call_args.data_len = 0; /*not used */
242 env_lock_mutex(rpc_data->rpc_lock);
243 send_rpc((void *)rpc_data->rpc, payload_size);
244 env_unlock_mutex(rpc_data->rpc_lock);
246 /* Wait for response from proxy on master */
247 env_acquire_sync_lock(rpc_data->sync_lock);
249 if (rpc_data->rpc_response->id == CLOSE_SYSCALL_ID) {
250 retval = rpc_data->rpc_response->sys_call_args.int_field1;
251 }
253 return retval;
254 }