1/*  kid.c -- ARMulator RDP/RDI interface:  ARM6 Instruction Emulator.
2    Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
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
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/*****************************************************************/
19/* The child process continues here...                           */
20/* It waits on a pipe from the parent and translates the RDP     */
21/* messages into RDI calls to the ARMulator passing RDP replies  */
22/* back up a pipe to the parent.                                 */
23/*****************************************************************/
24
25#include <sys/types.h>
26#include <signal.h>
27
28#include "armdefs.h"
29#include "dbg_conf.h"
30#include "dbg_hif.h"
31#include "dbg_rdi.h"
32#include "gdbhost.h"
33#include "communicate.h"
34
35/* The pipes between the two processes */
36extern int mumkid[2];
37extern int kidmum[2];
38
39/* The maximum number of file descriptors */
40extern int nfds;
41
42/* The machine name */
43#define MAXHOSTNAMELENGTH 64
44extern char localhost[MAXHOSTNAMELENGTH + 1];
45
46/* The socket number */
47extern unsigned int socketnumber;
48
49/* RDI interface */
50extern const struct RDIProcVec armul_rdi;
51
52static int MYrdp_level = 0;
53
54static int rdi_state = 0;
55
56/**************************************************************/
57/* Signal handler that terminates excecution in the ARMulator */
58/**************************************************************/
59void
60kid_handlesignal (int sig)
61{
62#ifdef DEBUG
63  fprintf (stderr, "Terminate ARMulator excecution\n");
64#endif
65  if (sig != SIGUSR1)
66    {
67      fprintf (stderr, "Unsupported signal.\n");
68      return;
69    }
70  armul_rdi.info (RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0);
71}
72
73/********************************************************************/
74/* Waits on a pipe from the socket demon for RDP and                */
75/* acts as an RDP to RDI interpreter on the front of the ARMulator. */
76/********************************************************************/
77void
78kid ()
79{
80  char *p, *q;
81  int i, j, k;
82  long outofthebag;
83  unsigned char c, d, message;
84  ARMword x, y, z;
85  struct sigaction action;
86  PointHandle point;
87  Dbg_ConfigBlock config;
88  Dbg_HostosInterface hostif;
89  struct Dbg_MCState *MCState;
90  char command_line[256];
91  struct fd_set readfds;
92
93  /* Setup a signal handler for SIGUSR1 */
94  action.sa_handler = kid_handlesignal;
95  action.sa_mask = 0;
96  action.sa_flags = 0;
97
98  sigaction (SIGUSR1, &action, (struct sigaction *) 0);
99
100  while (1)
101    {
102      /* Wait for ever */
103      FD_ZERO (&readfds);
104      FD_SET (mumkid[0], &readfds);
105
106      i = select (nfds, &readfds,
107		  (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
108
109      if (i < 0)
110	{
111	  perror ("select");
112	}
113
114      if (read (mumkid[0], &message, 1) < 1)
115	{
116	  perror ("read");
117	}
118
119      switch (message)
120	{
121	case RDP_Start:
122	  /* Open and/or Initialise */
123	  BAG_newbag ();
124
125	  MYread_char (mumkid[0], &c);	/* type */
126	  MYread_word (mumkid[0], &x);	/* memorysize */
127	  if (c & 0x2)
128	    MYread_char (mumkid[0], &d);	/* speed */
129	  config.processor = 0;
130	  config.memorysize = x;
131	  config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little;
132	  if (c & 0x8)
133	    config.bytesex = RDISex_DontCare;
134
135	  hostif.dbgprint = myprint;
136	  hostif.dbgpause = mypause;
137	  hostif.dbgarg = stdout;
138	  hostif.writec = mywritec;
139	  hostif.readc = myreadc;
140	  hostif.write = mywrite;
141	  hostif.gets = mygets;
142	  hostif.reset = mypause;	/* do nothing */
143	  hostif.resetarg = "Do I love resetting or what!\n";
144
145	  if (rdi_state)
146	    {
147	      /* we have restarted, so kill off the existing run.  */
148	      /* armul_rdi.close(); */
149	    }
150	  i = armul_rdi.open (c & 0x3, &config, &hostif, MCState);
151	  rdi_state = 1;
152
153	  MYwrite_char (kidmum[1], RDP_Return);
154	  MYwrite_char (kidmum[1], (unsigned char) i);
155
156	  x = ~0x4;
157	  armul_rdi.info (RDIVector_Catch, &x, 0);
158
159	  break;
160
161	case RDP_End:
162	  /* Close and Finalise */
163	  i = armul_rdi.close ();
164	  rdi_state = 0;
165	  MYwrite_char (kidmum[1], RDP_Return);
166	  MYwrite_char (kidmum[1], (unsigned char) i);
167	  break;
168
169	case RDP_Read:
170	  /* Read Memory Address */
171	  MYread_word (mumkid[0], &x);	/* address */
172	  MYread_word (mumkid[0], &y);	/* nbytes */
173	  p = (char *) malloc (y);
174	  i = armul_rdi.read (x, p, (unsigned *) &y);
175	  MYwrite_char (kidmum[1], RDP_Return);
176	  for (k = 0; k < y; k++)
177	    MYwrite_char (kidmum[1], p[k]);
178	  free (p);
179	  MYwrite_char (kidmum[1], (unsigned char) i);
180	  if (i)
181	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
182	  break;
183
184	case RDP_Write:
185	  /* Write Memory Address */
186	  MYread_word (mumkid[0], &x);	/* address */
187	  MYread_word (mumkid[0], &y);	/* nbytes */
188	  p = (char *) malloc (y);
189	  for (k = 0; k < y; k++)
190	    MYread_char (mumkid[0], &p[k]);
191	  i = armul_rdi.write (p, x, (unsigned *) &y);
192	  free (p);
193	  MYwrite_char (kidmum[1], RDP_Return);
194	  MYwrite_char (kidmum[1], (unsigned char) i);
195	  if (i)
196	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
197	  break;
198
199	case RDP_CPUread:
200	  /* Read CPU State */
201	  MYread_char (mumkid[0], &c);	/* mode */
202	  MYread_word (mumkid[0], &x);	/* mask */
203	  p = (char *) malloc (4 * RDINumCPURegs);
204	  i = armul_rdi.CPUread (c, x, (ARMword *) p);
205	  MYwrite_char (kidmum[1], RDP_Return);
206	  for (k = 1, j = 0; k != 0x80000000; k *= 2)
207	    if (k & x)
208	      MYwrite_word (kidmum[1], ((ARMword *) p)[j++]);
209	  free (p);
210	  if (i)
211	    MYwrite_char (kidmum[1], (unsigned char) j);
212	  MYwrite_char (kidmum[1], (unsigned char) i);
213	  break;
214
215	case RDP_CPUwrite:
216	  /* Write CPU State */
217	  MYread_char (mumkid[0], &c);	/* mode */
218	  MYread_word (mumkid[0], &x);	/* mask */
219
220	  p = (char *) malloc (4 * RDINumCPURegs);
221	  for (k = 1, j = 0; k != 0x80000000; k *= 2)
222	    if (k & x)
223	      MYread_word (mumkid[0], &(((ARMword *) p)[j++]));
224	  i = armul_rdi.CPUwrite (c, x, (ARMword *) p);
225	  MYwrite_char (kidmum[1], RDP_Return);
226	  MYwrite_char (kidmum[1], (unsigned char) i);
227	  free (p);
228	  break;
229
230	case RDP_CPread:
231	  /* Read Co-Processor State */
232	  MYread_char (mumkid[0], &c);	/* CPnum */
233	  MYread_word (mumkid[0], &x);	/* mask */
234	  p = q = (char *) malloc (16 * RDINumCPRegs);
235	  i = armul_rdi.CPread (c, x, (ARMword *) p);
236	  MYwrite_char (kidmum[1], RDP_Return);
237	  for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
238	    if (k & x)
239	      {
240		if ((c == 1 || c == 2) && k <= 128)
241		  {
242		    MYwrite_FPword (kidmum[1], q);
243		    q += 16;
244		  }
245		else
246		  {
247		    MYwrite_word (kidmum[1], *q);
248		    q += 4;
249		  }
250	      }
251	  free (p);
252	  if (i)
253	    MYwrite_char (kidmum[1], (unsigned char) j);
254	  MYwrite_char (kidmum[1], (unsigned char) i);
255	  break;
256
257	case RDP_CPwrite:
258	  /* Write Co-Processor State */
259	  MYread_char (mumkid[0], &c);	/* CPnum */
260	  MYread_word (mumkid[0], &x);	/* mask */
261	  p = q = (char *) malloc (16 * RDINumCPURegs);
262	  for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
263	    if (k & x)
264	      {
265		if ((c == 1 || c == 2) && k <= 128)
266		  {
267		    MYread_FPword (kidmum[1], q);
268		    q += 16;
269		  }
270		else
271		  {
272		    MYread_word (mumkid[0], (ARMword *) q);
273		    q += 4;
274		  }
275	      }
276	  i = armul_rdi.CPwrite (c, x, (ARMword *) p);
277	  MYwrite_char (kidmum[1], RDP_Return);
278	  MYwrite_char (kidmum[1], (unsigned char) i);
279	  free (p);
280	  break;
281
282	case RDP_SetBreak:
283	  /* Set Breakpoint */
284	  MYread_word (mumkid[0], &x);	/* address */
285	  MYread_char (mumkid[0], &c);	/* type */
286	  if ((c & 0xf) >= 5)
287	    MYread_word (mumkid[0], &y);	/* bound */
288	  i = armul_rdi.setbreak (x, c, y, &point);
289	  if (!MYrdp_level)
290	    BAG_putpair ((long) x, (long) point);
291	  MYwrite_char (kidmum[1], RDP_Return);
292	  if (MYrdp_level)
293	    MYwrite_word (kidmum[1], point);
294	  MYwrite_char (kidmum[1], (unsigned char) i);
295	  break;
296
297	case RDP_ClearBreak:
298	  /* Clear Breakpoint */
299	  MYread_word (mumkid[0], &point);	/* PointHandle */
300	  if (!MYrdp_level)
301	    {
302	      BAG_getsecond ((long) point, &outofthebag);	/* swap pointhandle for address */
303	      BAG_killpair_byfirst (outofthebag);
304	      point = outofthebag;
305	    }
306	  i = armul_rdi.clearbreak (point);
307	  MYwrite_char (kidmum[1], RDP_Return);
308	  MYwrite_char (kidmum[1], (unsigned char) i);
309	  break;
310
311	case RDP_SetWatch:
312	  /* Set Watchpoint */
313	  MYread_word (mumkid[0], &x);	/* address */
314	  MYread_char (mumkid[0], &c);	/* type */
315	  MYread_char (mumkid[0], &d);	/* datatype */
316	  if ((c & 0xf) >= 5)
317	    MYread_word (mumkid[0], &y);	/* bound */
318	  i = armul_rdi.setwatch (x, c, d, y, &point);
319	  MYwrite_char (kidmum[1], RDP_Return);
320	  MYwrite_word (kidmum[1], point);
321	  MYwrite_char (kidmum[1], (unsigned char) i);
322	  break;
323
324	case RDP_ClearWatch:
325	  /* Clear Watchpoint */
326	  MYread_word (mumkid[0], &point);	/* PointHandle */
327	  i = armul_rdi.clearwatch (point);
328	  MYwrite_char (kidmum[1], RDP_Return);
329	  MYwrite_char (kidmum[1], (unsigned char) i);
330	  break;
331
332	case RDP_Execute:
333	  /* Excecute */
334
335	  MYread_char (mumkid[0], &c);	/* return */
336
337#ifdef DEBUG
338	  fprintf (stderr, "Starting execution\n");
339#endif
340	  i = armul_rdi.execute (&point);
341#ifdef DEBUG
342	  fprintf (stderr, "Completed execution\n");
343#endif
344	  MYwrite_char (kidmum[1], RDP_Return);
345	  if (c & 0x80)
346	    MYwrite_word (kidmum[1], point);
347	  MYwrite_char (kidmum[1], (unsigned char) i);
348	  break;
349
350	case RDP_Step:
351	  /* Step */
352	  MYread_char (mumkid[0], &c);	/* return */
353	  MYread_word (mumkid[0], &x);	/* ninstr */
354	  point = 0x87654321;
355	  i = armul_rdi.step (x, &point);
356	  MYwrite_char (kidmum[1], RDP_Return);
357	  if (c & 0x80)
358	    MYwrite_word (kidmum[1], point);
359	  MYwrite_char (kidmum[1], (unsigned char) i);
360	  break;
361
362	case RDP_Info:
363	  /* Info */
364	  MYread_word (mumkid[0], &x);
365	  switch (x)
366	    {
367	    case RDIInfo_Target:
368	      i = armul_rdi.info (RDIInfo_Target, &y, &z);
369	      MYwrite_char (kidmum[1], RDP_Return);
370	      MYwrite_word (kidmum[1], y);	/* Loads of info... */
371	      MYwrite_word (kidmum[1], z);	/* Model */
372	      MYwrite_char (kidmum[1], (unsigned char) i);
373	      break;
374
375	    case RDISet_RDILevel:
376	      MYread_word (mumkid[0], &x);	/* arg1, debug level */
377	      i = armul_rdi.info (RDISet_RDILevel, &x, 0);
378	      if (i == RDIError_NoError)
379		MYrdp_level = x;
380	      MYwrite_char (kidmum[1], RDP_Return);
381	      MYwrite_char (kidmum[1], (unsigned char) i);
382	      break;
383
384	    case RDISet_Cmdline:
385	      for (p = command_line; MYread_char (mumkid[0], p), *p; p++)
386		;		/* String */
387	      i = armul_rdi.info (RDISet_Cmdline,
388				  (unsigned long *) command_line, 0);
389	      MYwrite_char (kidmum[1], RDP_Return);
390	      MYwrite_char (kidmum[1], (unsigned char) i);
391	      break;
392
393	    case RDIInfo_Step:
394	      i = armul_rdi.info (RDIInfo_Step, &x, 0);
395	      MYwrite_char (kidmum[1], RDP_Return);
396	      MYwrite_word (kidmum[1], x);
397	      MYwrite_char (kidmum[1], (unsigned char) i);
398	      break;
399
400	    case RDIVector_Catch:
401	      MYread_word (mumkid[0], &x);
402	      i = armul_rdi.info (RDIVector_Catch, &x, 0);
403	      MYwrite_char (kidmum[1], RDP_Return);
404	      MYwrite_char (kidmum[1], i);
405	      break;
406
407	    case RDIInfo_Points:
408	      i = armul_rdi.info (RDIInfo_Points, &x, 0);
409	      MYwrite_char (kidmum[1], RDP_Return);
410	      MYwrite_word (kidmum[1], x);
411	      MYwrite_char (kidmum[1], (unsigned char) i);
412	      break;
413
414	    default:
415	      fprintf (stderr, "Unsupported info code %d\n", x);
416	      break;
417	    }
418	  break;
419
420	case RDP_OSOpReply:
421	  /* OS Operation Reply */
422	  MYwrite_char (kidmum[1], RDP_Fatal);
423	  break;
424
425	case RDP_Reset:
426	  /* Reset */
427	  for (i = 0; i < 50; i++)
428	    MYwrite_char (kidmum[1], RDP_Reset);
429	  p = (char *) malloc (MAXHOSTNAMELENGTH + 5 + 20);
430	  sprintf (p, "Running on %s:%d\n", localhost, socketnumber);
431	  MYwrite_string (kidmum[1], p);
432	  free (p);
433
434	  break;
435	default:
436	  fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n");
437	  /* Hmm.. bad RDP operation */
438	  break;
439	}
440    }
441}
442
443
444/* Handles memory read operations until an OS Operation Reply Message is */
445/* encounterd. It then returns the byte info value (0, 1, or 2) and fills  */
446/* in 'putinr0' with the data if appropriate. */
447int
448wait_for_osreply (ARMword * reply)
449{
450  char *p, *q;
451  int i, j, k;
452  unsigned char c, d, message;
453  ARMword x, y, z;
454  struct sigaction action;
455  PointHandle point;
456  Dbg_ConfigBlock config;
457  Dbg_HostosInterface hostif;
458  struct Dbg_MCState *MCState;
459  char command_line[256];
460  struct fd_set readfds;
461
462#ifdef DEBUG
463  fprintf (stderr, "wait_for_osreply ().\n");
464#endif
465
466  /* Setup a signal handler for SIGUSR1 */
467  action.sa_handler = kid_handlesignal;
468  action.sa_mask = 0;
469  action.sa_flags = 0;
470
471  sigaction (SIGUSR1, &action, (struct sigaction *) 0);
472
473  while (1)
474    {
475      /* Wait for ever */
476      FD_ZERO (&readfds);
477      FD_SET (mumkid[0], &readfds);
478
479      i = select (nfds, &readfds,
480		  (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
481
482      if (i < 0)
483	{
484	  perror ("select");
485	}
486
487      if (read (mumkid[0], &message, 1) < 1)
488	{
489	  perror ("read");
490	}
491
492      switch (message)
493	{
494	case RDP_Read:
495	  /* Read Memory Address */
496	  MYread_word (mumkid[0], &x);	/* address */
497	  MYread_word (mumkid[0], &y);	/* nbytes */
498	  p = (char *) malloc (y);
499	  i = armul_rdi.read (x, p, (unsigned *) &y);
500	  MYwrite_char (kidmum[1], RDP_Return);
501	  for (k = 0; k < y; k++)
502	    MYwrite_char (kidmum[1], p[k]);
503	  free (p);
504	  MYwrite_char (kidmum[1], (unsigned char) i);
505	  if (i)
506	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
507	  break;
508
509	case RDP_Write:
510	  /* Write Memory Address */
511	  MYread_word (mumkid[0], &x);	/* address */
512	  MYread_word (mumkid[0], &y);	/* nbytes */
513	  p = (char *) malloc (y);
514	  for (k = 0; k < y; k++)
515	    MYread_char (mumkid[0], &p[k]);
516	  i = armul_rdi.write (p, x, (unsigned *) &y);
517	  free (p);
518	  MYwrite_char (kidmum[1], RDP_Return);
519	  MYwrite_char (kidmum[1], (unsigned char) i);
520	  if (i)
521	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
522	  break;
523
524	case RDP_OSOpReply:
525	  /* OS Operation Reply */
526	  MYread_char (mumkid[0], &c);
527	  if (c == 1)
528	    MYread_char (mumkid[0], (char *) reply);
529	  if (c == 2)
530	    MYread_word (mumkid[0], reply);
531	  return c;
532	  break;
533
534	default:
535	  fprintf (stderr,
536		   "HELP! Unaccounted-for message during OS request. \n");
537	  MYwrite_char (kidmum[1], RDP_Fatal);
538	}
539    }
540}
541