Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / cris / rvdummy.c
1 /* Test-driver for the remote-virtual-component simulator framework
2 for GDB, the GNU Debugger.
3
4 Copyright 2006-2022 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* Avoid any problems whatsoever building this program if we're not
22 also building hardware support. */
23
24 #if !WITH_HW
25 int
26 main (int argc, char *argv[])
27 {
28 return 2;
29 }
30 #else
31
32 /* This must come before any other includes. */
33 #include "defs.h"
34
35 #include "getopt.h"
36 #include "libiberty.h"
37
38 #include <stdio.h>
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #include <stdlib.h>
44 #include <string.h>
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
47 #endif
48
49 #include <sys/time.h>
50
51 #include <errno.h>
52
53 /* Not guarded in dv-sockser.c, so why here. */
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #include <netdb.h>
57 #include <sys/select.h>
58 #include <sys/socket.h>
59
60 enum rv_command {
61 RV_READ_CMD = 0,
62 RV_WRITE_CMD = 1,
63 RV_IRQ_CMD = 2,
64 RV_MEM_RD_CMD = 3,
65 RV_MEM_WR_CMD = 4,
66 RV_MBOX_HANDLE_CMD = 5,
67 RV_MBOX_PUT_CMD = 6,
68 RV_WATCHDOG_CMD = 7
69 };
70
71 enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
72
73 struct option longopts[] =
74 {
75 {"port", required_argument, NULL, OPT_PORT},
76 {"timeout", required_argument, NULL, OPT_TIMEOUT},
77 {"verbose", no_argument, NULL, OPT_VERBOSE},
78 {NULL, 0, NULL, 0}
79 };
80
81 int port = 10000;
82 time_t timeout = 30000;
83 char *progname = "(unknown)";
84 int verbose = 0;
85
86 /* Required forward-declarations. */
87 static void handle_input_file (int, char *);
88
89 /* Set up a "server" listening to the port in PORT for a raw TCP
90 connection. Return a file descriptor for the connection or -1 on
91 error. */
92
93 static int setupsocket (void)
94 {
95 int s;
96 socklen_t len;
97 int reuse = 1;
98 struct sockaddr_in sa_in;
99 struct sockaddr_in from;
100
101 len = sizeof (from);
102 memset (&from, 0, len);
103 memset (&sa_in, 0, sizeof (sa_in));
104
105 s = socket (AF_INET, SOCK_STREAM, 0);
106 if (s == -1)
107 return -1;
108
109 if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) != 0)
110 return -1;
111
112 sa_in.sin_port = htons (port);
113 sa_in.sin_family = AF_INET;
114
115 if (bind (s, (struct sockaddr *) & sa_in, sizeof sa_in) < 0)
116 return -1;
117
118 if (listen (s, 1) < 0)
119 return -1;
120
121 return accept (s, (struct sockaddr *) &from, &len);
122 }
123
124 /* Basic host-to-little-endian 32-bit value. Could use the BFD
125 machinery, but let's avoid it for this only dependency. */
126
127 static void
128 h2le32 (unsigned char *dest, unsigned int val)
129 {
130 dest[0] = val & 255;
131 dest[1] = (val >> 8) & 255;
132 dest[2] = (val >> 16) & 255;
133 dest[3] = (val >> 24) & 255;
134 }
135
136 /* Send a blob of data. */
137
138 static void
139 send_output (int fd, unsigned char *buf, int nbytes)
140 {
141 while (nbytes > 0)
142 {
143 ssize_t written = write (fd, buf, nbytes);
144 if (written < 0)
145 {
146 fprintf (stderr, "%s: write to socket failed: %s\n",
147 progname, strerror (errno));
148 exit (2);
149 }
150 nbytes -= written;
151 }
152 }
153
154 /* Receive a blob of data, NBYTES large. Compare to the first NCOMP
155 bytes of BUF; if not a match, write error message to stderr and
156 exit (2). Else put it in buf. */
157
158 static void
159 expect_input (int fd, unsigned char *buf, int nbytes, int ncomp)
160 {
161 unsigned char byt;
162 int i;
163
164 for (i = 0; i < nbytes; i++)
165 {
166 int r;
167
168 do
169 {
170 errno = 0;
171 r = read (fd, &byt, 1);
172 }
173 while (r <= 0 && (r == 0 || errno == EAGAIN));
174
175 if (r != 1)
176 {
177 fprintf (stderr, "%s: read from socket failed: %s",
178 progname, strerror (errno));
179 exit (2);
180 }
181
182 if (i < ncomp && byt != buf[i])
183 {
184 int j;
185 fprintf (stderr, "%s: unexpected input,\n ", progname);
186 if (i == 0)
187 fprintf (stderr, "nothing,");
188 else
189 for (j = 0; j < i; j++)
190 fprintf (stderr, "%02x", buf[j]);
191 fprintf (stderr, "\nthen %02x instead of %02x\n", byt, buf[i]);
192 exit (2);
193 }
194 else
195 buf[i] = byt;
196 }
197 }
198
199 /* Handle everything about a nil-terminated line of input.
200 Call exit (2) on error with error text on stderr. */
201
202 static void
203 handle_input (int fd, char *buf, char *fname, int lineno)
204 {
205 int nbytes = 0;
206 int n = -1;
207 char *s = buf + 2;
208 unsigned int data;
209 static unsigned char bytes[1024];
210 int i;
211
212 memset (bytes, 0, sizeof bytes);
213 lineno++;
214
215 if (buf[1] != ',')
216 goto syntax_error;
217
218 switch (buf[0])
219 {
220 /* Comment characters and empty lines. */
221 case 0: case '!': case '#':
222 break;
223
224 /* Include another file. */
225 case '@':
226 handle_input_file (fd, s);
227 break;
228
229 /* Raw input (to be expected). */
230 case 'i':
231 do
232 {
233 n = -1;
234 sscanf (s, "%02x%n", &data, &n);
235 s += n;
236 if (n > 0)
237 bytes[nbytes++] = data;
238 }
239 while (n > 0);
240 expect_input (fd, bytes, nbytes, nbytes);
241 if (verbose)
242 {
243 printf ("i,");
244 for (i = 0; i < nbytes; i++)
245 printf ("%02x", bytes[i]);
246 printf ("\n");
247 }
248 break;
249
250 /* Raw output (to be written). */
251 case 'o':
252 do
253 {
254 n = -1;
255 sscanf (s, "%02x%n", &data, &n);
256 if (n > 0)
257 {
258 s += n;
259 bytes[nbytes++] = data;
260 }
261 }
262 while (n > 0);
263 if (*s != 0)
264 goto syntax_error;
265 send_output (fd, bytes, nbytes);
266 if (verbose)
267 {
268 printf ("o,");
269 for (i = 0; i < nbytes; i++)
270 printf ("%02x", bytes[i]);
271 printf ("\n");
272 }
273 break;
274
275 /* Read a register. */
276 case 'r':
277 {
278 unsigned int addr;
279 sscanf (s, "%x,%x%n", &addr, &data, &n);
280 if (n < 0 || s[n] != 0)
281 goto syntax_error;
282 bytes[0] = 11;
283 bytes[1] = 0;
284 bytes[2] = RV_READ_CMD;
285 h2le32 (bytes + 3, addr);
286 expect_input (fd, bytes, 11, 7);
287 h2le32 (bytes + 7, data);
288 send_output (fd, bytes, 11);
289 if (verbose)
290 printf ("r,%x,%x\n", addr, data);
291 }
292 break;
293
294 /* Write a register. */
295 case 'w':
296 {
297 unsigned int addr;
298 sscanf (s, "%x,%x%n", &addr, &data, &n);
299 if (n < 0 || s[n] != 0)
300 goto syntax_error;
301 bytes[0] = 11;
302 bytes[1] = 0;
303 bytes[2] = RV_WRITE_CMD;
304 h2le32 (bytes + 3, addr);
305 h2le32 (bytes + 7, data);
306 expect_input (fd, bytes, 11, 11);
307 send_output (fd, bytes, 11);
308 if (verbose)
309 printf ("w,%x,%x\n", addr, data);
310 }
311 break;
312
313 /* Wait for some milliseconds. */
314 case 't':
315 {
316 int del = 0;
317 struct timeval to;
318 sscanf (s, "%d%n", &del, &n);
319 if (n < 0 || s[n] != 0 || del == 0)
320 goto syntax_error;
321
322 to.tv_sec = del / 1000;
323 to.tv_usec = (del % 1000) * 1000;
324
325 if (select (0, NULL, NULL, NULL, &to) != 0)
326 {
327 fprintf (stderr, "%s: problem waiting for %d ms:\n %s\n",
328 progname, del, strerror (errno));
329 exit (2);
330 }
331 if (verbose)
332 printf ("t,%d\n", del);
333 }
334 break;
335
336 /* Expect a watchdog command. */
337 case 'W':
338 if (*s != 0)
339 goto syntax_error;
340 bytes[0] = 3;
341 bytes[1] = 0;
342 bytes[2] = RV_WATCHDOG_CMD;
343 expect_input (fd, bytes, 3, 3);
344 if (verbose)
345 printf ("W\n");
346 break;
347
348 /* Send an IRQ notification. */
349 case 'I':
350 sscanf (s, "%x%n", &data, &n);
351 if (n < 0 || s[n] != 0)
352 goto syntax_error;
353 bytes[0] = 7;
354 bytes[1] = 0;
355 bytes[2] = RV_IRQ_CMD;
356 h2le32 (bytes + 3, data);
357 send_output (fd, bytes, 7);
358 if (verbose)
359 printf ("I,%x\n", data);
360 break;
361
362 /* DMA store (to CPU). */
363 case 's':
364 {
365 unsigned int addr;
366 sscanf (s, "%x,%n", &addr, &n);
367
368 if (n < 0 || s[n] == 0)
369 goto syntax_error;
370 s += n;
371 do
372 {
373 n = -1;
374 sscanf (s, "%02x%n", &data, &n);
375 if (n > 0)
376 {
377 s += n;
378 bytes[11 + nbytes++] = data;
379 }
380 }
381 while (n > 0);
382
383 if (*s != 0)
384 goto syntax_error;
385 h2le32 (bytes, nbytes + 11);
386 bytes[2] = RV_MEM_WR_CMD;
387 h2le32 (bytes + 3, addr);
388 h2le32 (bytes + 7, nbytes);
389 send_output (fd, bytes, nbytes + 11);
390 if (verbose)
391 {
392 printf ("s,%x,", addr);
393 for (i = 0; i < nbytes; i++)
394 printf ("%02x", bytes[i]);
395 printf ("\n");
396 }
397 }
398 break;
399
400 /* DMA load (from CPU). */
401 case 'l':
402 {
403 unsigned int addr;
404 sscanf (s, "%x,%n", &addr, &n);
405
406 if (n < 0 || s[n] == 0)
407 goto syntax_error;
408 s += n;
409 do
410 {
411 n = -1;
412 sscanf (s, "%02x%n", &data, &n);
413 if (n > 0)
414 {
415 s += n;
416 bytes[11 + nbytes++] = data;
417 }
418 }
419 while (n > 0);
420
421 if (*s != 0)
422 goto syntax_error;
423 h2le32 (bytes, nbytes + 11);
424 bytes[0] = 11;
425 bytes[1] = 0;
426 bytes[2] = RV_MEM_RD_CMD;
427 h2le32 (bytes + 3, addr);
428 h2le32 (bytes + 7, nbytes);
429 send_output (fd, bytes, 11);
430 bytes[0] = (nbytes + 11) & 255;
431 bytes[1] = ((nbytes + 11) >> 8) & 255;
432 expect_input (fd, bytes, nbytes + 11, nbytes + 11);
433 if (verbose)
434 {
435 printf ("l,%x,", addr);
436 for (i = 0; i < nbytes; i++)
437 printf ("%02x", bytes[i]);
438 printf ("\n");
439 }
440 }
441 break;
442
443 syntax_error:
444 default:
445 fprintf (stderr, "%s: invalid command line in %s:%d:\n %s",
446 progname, fname, lineno, strerror (errno));
447 exit (2);
448 }
449 }
450
451 /* Loop over the contents of FNAME, using handle_input to parse each line.
452 Errors to stderr, exit (2). */
453
454 static void
455 handle_input_file (int fd, char *fname)
456 {
457 static char buf[2048] = {0};
458 int lineno = 0;
459 FILE *f = fopen (fname, "r");
460
461 if (f == NULL)
462 {
463 fprintf (stderr, "%s: problem opening %s: %s\n",
464 progname, fname, strerror (errno));
465 exit (2);
466 }
467
468 /* Let's cut the buffer short, so we always get a newline. */
469 while (fgets (buf, sizeof (buf) - 1, f) != NULL)
470 {
471 buf[strlen (buf) - 1] = 0;
472 lineno++;
473 handle_input (fd, buf, fname, lineno);
474 }
475
476 fclose (f);
477 }
478
479 int
480 main (int argc, char *argv[])
481 {
482 int optc;
483 int fd;
484 FILE *f;
485 int i;
486
487 progname = argv[0];
488 while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)
489 switch (optc)
490 {
491 case OPT_PORT:
492 port = atoi (optarg);
493 break;
494
495 case OPT_TIMEOUT:
496 timeout = (time_t) atoi (optarg);
497 break;
498
499 case OPT_VERBOSE:
500 verbose = 1;
501 break;
502 }
503
504 fd = setupsocket ();
505 if (fd == -1)
506 {
507 fprintf (stderr, "%s: problem setting up the connection: %s\n",
508 progname, strerror (errno));
509 exit (2);
510 }
511
512 for (i = optind; i < argc; i++)
513 handle_input_file (fd, argv[i]);
514
515 /* FIXME: option-controlled test for remaining input? */
516 close (fd);
517 return 1;
518 }
519 #endif
This page took 0.051811 seconds and 4 git commands to generate.