rvdummy.c 11 KB

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