/* Remote debugging with the XLNT Designs, Inc (XDI) NetROM.
- Copyright 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1995, 1998, 1999, 2000
+ Free Software Foundation, Inc.
Contributed by:
- Roger Moyers
- XLNT Designs, Inc.
- 15050 Avenue of Science, Suite 106
- San Diego, CA 92128
- (619)487-9320
- roger@xlnt.com
+ Roger Moyers
+ XLNT Designs, Inc.
+ 15050 Avenue of Science, Suite 106
+ San Diego, CA 92128
+ (619)487-9320
+ roger@xlnt.com
Adapted from work done at Cygnus Support in remote-nindy.c,
later merged in by Stan Shebs at Cygnus.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcmd.h"
-#include <string.h>
-#include "inferior.h"
-#include "wait.h"
-#include "value.h"
-#include <ctype.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <stropts.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-#include "terminal.h"
+#include "serial.h"
#include "target.h"
-#include "gdbcore.h"
-
-/* Packet header found on every packet sent to/from GDB. */
-
-typedef struct gpkthdr {
- unsigned char csum; /* Check sum */
- unsigned char seq_num; /* Sequence number */
- unsigned short len; /* Number of bytes in packet */
- unsigned char cmd; /* GDB command */
- unsigned char pad[3];
- unsigned long addr; /* Address if needed */
- unsigned long datalen; /* # of bytes to read/write */
-} GPKTHDR;
-
-#define GDB_START_DELIMITER '['
-#define GDB_END_DELIMITER ']'
-
-/* GDB requests. */
-
-#define GDB_QUERY_CMD 0x01
-#define GDB_STATUS 0x02
-#define GDB_READ_REGS 0x03
-#define GDB_WRITE_REGS 0x04
-#define GDB_READ_MEM 0x05
-#define GDB_WRITE_MEM 0x06
-#define GDB_CONTINUE 0x07
-#define GDB_STEP 0x08
-
-/* Responses. */
-
-#define GDB_ACK 0x11
-#define GDB_NACK 0x12
-#define GDB_READ_REG_RESP 0x13
-#define GDB_READ_MEM_RESP 0x14
-#define GDB_WRITE_REG_RESP 0x15
-#define GDB_WRITE_MEM_RESP 0x16
-
-#define GDB_BP_TRAP "05"
-#define GDB_BUSERR_TRAP "10"
-#define GDB_ILLOP_TRAP "40"
-
-#define GDB_ACK_VALUE "OK"
/* Default ports used to talk with the NetROM. */
-#define DEFAULT_NETROM_TARGET_PORT 1235
#define DEFAULT_NETROM_LOAD_PORT 1236
#define DEFAULT_NETROM_CONTROL_PORT 1237
-#define UC(b) (((long)b)&0xff)
-
-#define NROM_BUF_SIZE 2048
-#define MAX_SEND_ATTEMPTS 10
-#define READ_BUF_SIZE 2048
-
-/* Definitions for filetype. */
-
-#define BINARY_FTYPE 0
-#define MOTO_SREC 1
-#define INTEL_HEX 2
-
-#if 0 /* for debugging, if anyone cares */
-static char *GCMDTYPE[] = {
- "ZERO",
- "GDB_QUERY",
- "GDB_STATUS",
- "GDB_READ_REGS",
- "GDB_WRITE_REGS",
- "GDB_READ_MEM",
- "GDB_WRITE_MEM",
- "GDB_CONTINUE",
- "GDB_STEP",
- "CMD9",
- "CMDA",
- "CMDB",
- "CMDC",
- "CMDD",
- "CMDE",
- "CMDF",
- "RESP0",
- "GDB_ACK",
- "GDB_NACK",
- "GDB_READ_REG_RESP",
- "GDB_READ_MEM_RESP",
- "GDB_WRITE_REG_RESP",
- "GDB_WRITE_MEM_RESP"
-};
-#endif
-
-static void nrom_attach PARAMS ((char *, int));
-
-static int nrom_can_run PARAMS ((void));
-
-static void nrom_close PARAMS ((int));
-
-static void nrom_create_inferior PARAMS ((char *, char *, char **));
-
-static void nrom_detach PARAMS ((char *, int));
-
-static void nrom_fetch_registers PARAMS ((int));
-
-static void nrom_files_info PARAMS ((struct target_ops *));
-
-static void nrom_kill PARAMS ((void));
-
-static void nrom_load PARAMS ((char *, int));
-
-static void nrom_mourn PARAMS ((void));
-
-static void nrom_open PARAMS ((char *,int));
-
-static void nrom_resume PARAMS ((int, int, enum target_signal));
-
-static void nrom_prepare_to_store PARAMS ((void));
-
-static void nrom_store_registers PARAMS ((int));
-
-static int nrom_wait PARAMS ((int pid, struct target_waitstatus *status));
-
-static int nrom_xfer_inferior_memory PARAMS ((CORE_ADDR, char *, int, int,
- struct target_ops *));
-
-static int nrom_write_inferior_memory PARAMS ((CORE_ADDR, char *, int));
-
-static int nrom_read_inferior_memory PARAMS ((CORE_ADDR, char *, int));
+static void nrom_close (int quitting);
/* New commands. */
-static void nrom_set_target_port PARAMS ((char *, int));
-
-static void nrom_set_control_port PARAMS ((char *, int));
-
-static void nrom_set_load_port PARAMS ((char *, int));
-
-static void nrom_set_ipaddr PARAMS ((char *, int));
-
-static void nrom_set_filetype PARAMS ((char *, int));
-
-static void nrom_show_status PARAMS ((char *, int));
-
-static void nrom_passthru PARAMS ((char *, int));
-
-/* Packet functions. */
-
-static void build_pkt PARAMS ((int, unsigned char *, long,
- unsigned char *, unsigned long, unsigned long,
- int));
-
-static int compute_csum PARAMS ((unsigned char *, int));
-
-#if 0
-static void dump_pkt PARAMS ((GPKTHDR *, unsigned char *));
-#endif
-
-static int get_seq_number PARAMS ((void));
-
-static char *hex2mem PARAMS ((char *, char *, int));
-
-static char *mem2hex PARAMS ((char *, char *, int));
-
-static void nrom_send PARAMS ((int, char *, int, long, long, char *));
-
-static void send_query_cmd PARAMS ((void));
-
-static int send_pkt PARAMS ((int, char *, int, long, int));
-
-static int read_pkt PARAMS ((char *));
-
-static void send_query_cmd PARAMS ((void));
-
-static int tohex PARAMS ((int));
-
-static int parse_pkt PARAMS ((unsigned char *, GPKTHDR *, char *));
-
-static int writen PARAMS ((int, char *, int));
-
-/* Private globals. */
+static void nrom_passthru (char *, int);
/* We talk to the NetROM over these sockets. */
-static int nrom_load_sock = -1;
-static int nrom_targ_sock = -1;
-static int nrom_ctrl_sock = -1;
-
-/* For binding to the socket we ned a sockaddr_in structure. */
-
-static struct sockaddr_in nrom_sin;
-
-/* The IP Address of the NetROM is needed so we know who to talk to. */
-
-static unsigned long nrom_ipaddr = 0;
+static struct serial *load_desc = NULL;
+static struct serial *ctrl_desc = NULL;
static int load_port = DEFAULT_NETROM_LOAD_PORT;
-static int target_port = DEFAULT_NETROM_TARGET_PORT;
static int control_port = DEFAULT_NETROM_CONTROL_PORT;
-static int nrom_filetype = BINARY_FTYPE;
-
-static unsigned char host_seq_num = 0;
-
-static char hexchars[] = "0123456789abcdef";
-
-static char freadbuf[READ_BUF_SIZE];
-
-static char readbuf[NROM_BUF_SIZE];
-static int bufdata = 0;
-static int bufindex = 0;
-
-static char workbuf[NROM_BUF_SIZE];
-static char sendbuf[NROM_BUF_SIZE];
+static char nrom_hostname[100];
/* Forward data declaration. */
extern struct target_ops nrom_ops;
-/* This routine builds a packet to send to gdb running on the host. */
-
-static void
-build_pkt (cmd, data, datalen, pkt, addr, len, seq)
- int cmd;
- unsigned char *data;
- long datalen;
- unsigned char *pkt;
- unsigned long addr;
- unsigned long len;
- int seq;
-{
- GPKTHDR phdr;
- char *dptr;
- char *pktptr;
- unsigned char csum;
- int plen;
-
- phdr.csum = 0;
- phdr.len = sizeof(GPKTHDR) + datalen;
- phdr.seq_num = seq;
- phdr.cmd = cmd;
- phdr.pad[0] = phdr.pad[1] = phdr.pad[2] = 0;
- phdr.addr = addr;
- phdr.datalen = len;
- /* Convert packet header to ASCII. */
- dptr = mem2hex ((char *) &phdr, pkt, sizeof(GPKTHDR));
-
- /* Calculate pkt length now that it is converted. */
- plen = (int) ((unsigned long)dptr - (unsigned long)pkt) + datalen;
- /* Put data in packet. */
- if (datalen > 0)
- memcpy (dptr, data, datalen);
-
- /* Compute checksum. For computing checksum we skip first two bytes
- since this is where the checksum will go. */
- pktptr = pkt + 2;
- csum = compute_csum (pktptr, plen - 2);
- *pkt++ = hexchars[csum >> 4];
- *pkt++ = hexchars[csum % 16];
- dptr += datalen;
- *dptr = '\0';
-}
+/* Scan input from the remote system, until STRING is found. Print chars that
+ don't match. */
static int
-compute_csum (data, len)
- unsigned char *data;
- int len;
-{
- unsigned char csum;
-
- csum = 0;
- while (len > 0)
- {
- csum += *data++;
- --len;
- }
- return csum;
-}
-
-#if 0 /* for debugging, if anyone cares */
-static void
-dump_pkt (hdr, data)
- GPKTHDR *hdr;
- unsigned char *data;
+expect (char *string)
{
- int i;
+ char *p = string;
+ int c;
- printf_filtered ("PACKET: csum = %x,seq = %d,len = %d\n",hdr->csum,hdr->seq_num,
- hdr->len);
+ immediate_quit++;
- printf_filtered ("cmd = %s,addr = %x, datalen = %d\n", GCMDTYPE[hdr->cmd],
- hdr->addr,hdr->datalen);
- if (hdr->datalen)
+ while (1)
{
- for (i = 0; i < hdr->datalen * 2; i++)
- printf_filtered ("%x",data[i]);
- printf_filtered ("\n");
- }
-}
-#endif
-
-static int
-get_seq_number()
-{
- return host_seq_num++;
-}
-
-int
-hex (ch)
- int ch;
-{
- if ((ch >= 'a') && (ch <= 'f'))
- return (ch - 'a' + 10);
- if((ch >= 'A') && (ch <= 'F'))
- return ((ch - 'A') + 10);
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- return 0;
-}
-
-/* Convert the hex array pointed to by buf into binary to be placed in mem
- return a pointer to the character AFTER the last byte written. */
+ c = SERIAL_READCHAR (ctrl_desc, 5);
-static char*
-hex2mem(buf, mem, count)
- char* buf;
- char* mem;
- int count;
-{
- int i;
- unsigned char ch;
-
- for (i = 0; i < count; i++)
- {
- ch = hex(*buf++) << 4;
- ch = ch + hex(*buf++);
- *mem++ = ch;
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit--;
+ return 0;
+ }
+ }
+ else
+ {
+ fputc_unfiltered (c, gdb_stdout);
+ p = string;
+ if (c == *p)
+ p++;
+ }
}
- return mem;
}
-/* Convert the memory pointed to by mem into hex, placing result in buf
- return a pointer to the last char put in buf (null) */
-
-static char *
-mem2hex (mem, buf, count)
- char* mem;
- char* buf;
- int count;
+static void
+nrom_kill (void)
{
- int i;
- unsigned char ch;
-
- for (i = 0; i < count; i++)
- {
- ch = *mem++;
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch % 16];
- }
- *buf = 0;
- return buf;
+ nrom_close (0);
}
-static int
-nrom_control_send (s, nbytes)
- char *s;
- int nbytes;
+static struct serial *
+open_socket (char *name, int port)
{
- long len;
- char buf[10];
+ char sockname[100];
+ struct serial *desc;
- /* clear leading characters */
- /* FIXME: The ioctl uses here seem bogus to me. -sts */
- len = 1;
- while (len > 0)
- {
- if (ioctl (nrom_ctrl_sock, FIONREAD, &len) < 0)
- {
- perror ("nrom_control_send ioctl");
- return (-1);
- }
- if (len > 0)
- {
- if (read (nrom_ctrl_sock, buf, 1) < 0)
- {
- perror ("nrom_control_send read");
- return (-1);
- }
- }
- }
-
- if (remote_debug)
- printf_filtered ("nrom_control_send: sending '%s' (%d bytes) to NetROM\n",
- s, nbytes);
-
- if (writen (nrom_ctrl_sock, s, nbytes) < 0)
- {
- perror ("nrom_control_send");
- return (-1);
- }
+ sprintf (sockname, "%s:%d", name, port);
+ desc = SERIAL_OPEN (sockname);
+ if (!desc)
+ perror_with_name (sockname);
- /* clear trailing characters */
- len = 1;
- while (len > 0)
- {
- if (ioctl (nrom_ctrl_sock, FIONREAD, &len) < 0)
- {
- perror ("nrom_control_send ioctl");
- return (-1);
- }
- if (len > 0)
- {
- if (read (nrom_ctrl_sock, buf, 1) < 0)
- {
- perror ("nrom_control_send read");
- return (-1);
- }
- }
- }
- return 0;
+ return desc;
}
static void
-nrom_kill ()
+load_cleanup (void)
{
+ SERIAL_CLOSE (load_desc);
+ load_desc = NULL;
}
/* Download a file specified in ARGS to the netROM. */
static void
-nrom_load (args, fromtty)
- char *args;
- int fromtty;
+nrom_load (char *args, int fromtty)
{
int fd, rd_amt, fsize;
- struct sockaddr_in sin;
bfd *pbfd;
asection *section;
char *downloadstring = "download 0\n";
+ struct cleanup *old_chain;
/* Tell the netrom to get ready to download. */
- if (nrom_control_send (downloadstring, strlen (downloadstring)) < 0)
+ if (SERIAL_WRITE (ctrl_desc, downloadstring, strlen (downloadstring)))
error ("nrom_load: control_send() of `%s' failed", downloadstring);
- /* Wait for the download daemon to start up. */
- sleep (1);
+ expect ("Waiting for a connection...\n");
- nrom_load_sock = socket (AF_INET, SOCK_STREAM, 0);
- if (nrom_load_sock == -1)
- error ("Could not create download socket, error %d", errno);
+ load_desc = open_socket (nrom_hostname, load_port);
- memset (&sin, 0, sizeof(struct sockaddr_in));
- sin.sin_family = AF_INET;
- sin.sin_port = htons (load_port);
- sin.sin_addr.s_addr = htonl (nrom_ipaddr);
-
- if (connect (nrom_load_sock, &sin, sizeof(sin)) == -1)
- error ("Connect failed, error %d", errno);
+ old_chain = make_cleanup (load_cleanup, 0);
pbfd = bfd_openr (args, 0);
if (pbfd)
{
- if (!bfd_check_format (pbfd, bfd_object))
+ make_cleanup (bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
error ("\"%s\": not in executable format: %s",
args, bfd_errmsg (bfd_get_error ()));
- for (section = pbfd->sections; section; section = section->next)
+ for (section = pbfd->sections; section; section = section->next)
{
if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
{
{
char buffer[1024];
int count;
-
+
count = min (section_size, 1024);
bfd_get_section_contents (pbfd, section, buffer, fptr,
count);
- writen (nrom_load_sock, buffer, count);
+ SERIAL_WRITE (load_desc, buffer, count);
section_address += count;
fptr += count;
section_size -= count;
}
}
- else /* BSS and such */
+ else
+ /* BSS and such */
{
printf_filtered ("[section %s: not loading]\n",
section_name);
else
error ("\"%s\": Could not open", args);
- close (nrom_load_sock);
-}
-
-/* This is called not only when we first attach, but also when the
- user types "run" after having attached. */
-
-static void
-nrom_create_inferior (execfile, args, env)
- char *execfile;
- char *args;
- char **env;
-{
+ do_cleanups (old_chain);
}
/* Open a connection to the remote NetROM devices. */
static void
-nrom_open (name, from_tty)
- char *name;
- int from_tty;
+nrom_open (char *name, int from_tty)
{
int errn;
- if (name)
- nrom_set_ipaddr (name, from_tty);
- else if (nrom_ipaddr == 0)
+ if (!name || strchr (name, '/') || strchr (name, ':'))
error (
-"To open a NetROM connection, you must specify the hostname\n\
+ "To open a NetROM connection, you must specify the hostname\n\
or IP address of the NetROM device you wish to use.");
- push_target (&nrom_ops);
-
- /* Create the socket used for talking with the target. */
- nrom_targ_sock = socket (AF_INET, SOCK_STREAM, 0);
-
- /* Bind the socket. */
- nrom_sin.sin_family = AF_INET;
- nrom_sin.sin_port = htons (target_port);
- nrom_sin.sin_addr.S_un.S_addr = htonl (nrom_ipaddr);
+ strcpy (nrom_hostname, name);
- /* Connect to the remote host. */
- if (connect (nrom_targ_sock, &nrom_sin, sizeof(nrom_sin)) == -1)
- error ("Connect failed, error %d", errno);
+ target_preopen (from_tty);
- /* Create the socket used for talking with the debugger services. */
- nrom_ctrl_sock = socket (AF_INET, SOCK_STREAM, 0);
+ unpush_target (&nrom_ops);
- /* Bind the socket. */
- nrom_sin.sin_family = AF_INET;
- nrom_sin.sin_port = htons (control_port);
- nrom_sin.sin_addr.S_un.S_addr = htonl (nrom_ipaddr);
+ ctrl_desc = open_socket (nrom_hostname, control_port);
- /* Connect to the remote host. */
- if (connect (nrom_ctrl_sock, &nrom_sin, sizeof(nrom_sin)) == -1)
- {
- errn = errno;
- close (nrom_targ_sock);
- error ("Connect control_socket failed, error %d", errn);
- }
+ push_target (&nrom_ops);
if (from_tty)
- {
- unsigned char *i;
-
- printf_filtered ("Connected to NetROM device \"%s\"", name);
- i = (unsigned char *) &nrom_ipaddr;
- printf_filtered (" (%d.%d.%d.%d)\n",
- UC(i[0]), UC(i[1]), UC(i[2]), UC(i[3]));
- }
-}
-
-static int
-nrom_can_run ()
-{
- return 1;
+ printf_filtered ("Connected to NetROM device \"%s\"\n", nrom_hostname);
}
/* Close out all files and local state before this target loses control. */
static void
-nrom_close (quitting)
- int quitting;
-{
-}
-
-/* Attach to the target that is already loaded and possibly running */
-
-static void
-nrom_attach (args, from_tty)
- char *args;
- int from_tty;
-{
- int nwaiting;
- char buf[10];
-
- if (from_tty)
- printf_filtered ("Attaching to NetROM\n");
-
- /* clear any pending data on the socket */
- printf_filtered ("Waiting for pending data to arrive... ");
- fflush(stdout);
- sleep(1);
- printf_filtered ("that's long enough!\n");
- while (1)
- {
- if (ioctl(nrom_targ_sock, FIONREAD, &nwaiting) != 0)
- {
- /* couldn't determine data left */
- perror("nrom_attach: ioctl FIONREAD");
- break;
- }
- else if (nwaiting > 0)
- {
- /* flush incoming data */
- while (nwaiting != 0)
- {
- if (read (nrom_targ_sock, buf, 1) < 0)
- {
- perror("nrom_attach: read");
- exit(1);
- }
- if (remote_debug > 2)
- putc(buf[0], stdout);
- nwaiting--;
- }
- }
- else
- {
- /* no more data */
- break;
- }
- }
- printf_filtered ("Pending data removed\n");
-
- /* We will get a task spawn event immediately. */
- send_query_cmd ();
- target_has_execution = 1;
-/*
- start_remote();
-*/
-}
-
-/* Terminate the open connection to the remote debugger. Use this
- when you want to detach and do something else with your gdb. */
-
-static void
-nrom_detach (args, from_tty)
- char *args;
- int from_tty;
-{
- pop_target ();
- if (from_tty)
- printf_filtered ("Ending remote debugging\n");
-}
-
-/* Tell the remote machine to resume. */
-
-static void
-nrom_prepare_to_store()
-{
-}
-
-static void
-nrom_resume (pid, step, siggnal)
- int pid, step;
- enum target_signal siggnal;
-{
- if (step)
- send_pkt (GDB_STEP, NULL, 0, 0, 0);
- else
- send_pkt (GDB_CONTINUE, NULL, 0, 0, 0);
-}
-
-/* Wait until the remote machine stops, then return,
- storing status in STATUS just as `wait' would. */
-
-static int
-nrom_wait (pid, status)
- int pid;
- struct target_waitstatus *status;
-{
- static char pkt[NROM_BUF_SIZE], inbuf[NROM_BUF_SIZE];
- GPKTHDR phdr;
-
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = 0;
-
- while (1)
- {
- if (read_pkt (pkt) == -1)
- continue;
-
- if (parse_pkt (pkt, &phdr, inbuf) < 0)
- {
- if (remote_debug)
- printf_filtered ("Bad packet in nrom_wait\n");
- send_query_cmd ();
- continue;
- }
-
- /* Got good packet. Verify command is right. */
- if (phdr.cmd != GDB_STATUS)
- {
- /* Wrong response. Resend command. */
- send_query_cmd ();
- continue;
- }
- /* Packet is fine. Exit loop. */
- return inferior_pid;
- }
-}
-
-/* Read the remote registers. */
-
-static void
-nrom_fetch_registers (regno)
- int regno;
+nrom_close (int quitting)
{
- char buf[NROM_BUF_SIZE];
- char regs[REGISTER_BYTES];
- int i;
-
-#ifdef DEBUG
- printf_filtered ("reg no is %d\n",regno);
-#endif
-
- nrom_send (GDB_READ_REGS, NULL, 0, -1, 0, buf);
- memcpy (regs, buf, REGISTER_BYTES);
- for (i = 0; i < NUM_REGS; i++)
- supply_register (i, ®s[REGISTER_BYTE(i)]);
-#ifdef NO_SINGLE_REG
- nrom_send (GDB_READ_REGS, NULL, 0, regno, 0, buf);
- if (regno != -1)
- supply_register(regno,buf);
- else
- {
- memcpy (regs, buf, REGISTER_BYTES);
- for (i = 0; i < NUM_REGS; i++)
- supply_register (i, ®s[REGISTER_BYTE(i)]);
- }
-#endif
-}
-
-static void
-nrom_send (cmd, data, datalen, addr, len, resp)
- int cmd;
- char *data;
- int datalen;
- long addr;
- long len;
- char *resp;
-{
- GPKTHDR phdr;
- char inbuf[NROM_BUF_SIZE];
-
- while (1)
- {
- while (send_pkt (cmd, data, datalen, addr, len) < 0)
- ;
- if (read_pkt (inbuf) != -1)
- {
- if (parse_pkt (inbuf, &phdr, resp) < 0)
- continue;
- if (phdr.cmd != GDB_NACK)
- return;
- }
- }
-}
-
-static void
-nrom_set_filetype (args, fromtty)
- char *args;
- int fromtty;
-{
- if (args[0] == 'b')
- nrom_filetype = BINARY_FTYPE;
- else if (args[0] == 'm')
- nrom_filetype = MOTO_SREC;
- else if (args[0] == 'i')
- nrom_filetype = INTEL_HEX;
- else
- printf_filtered ("Unknown file type\n");
-}
-
-static void
-nrom_set_ipaddr (args, fromtty)
- char *args;
- int fromtty;
-{
- struct hostent *h;
- char buf[10];
- int i,j,val;
- unsigned long newip = 0;
-
- /* First do a check to see if they typed in a hostname. */
- if (!(*args))
- error ("Please enter a hostname or IP address");
-
- h = gethostbyname (args);
- if (h)
- {
- /* It is a hostname. We just need the ipaddress. */
- memcpy (&nrom_ipaddr, h->h_addr, h->h_length);
- }
- else
- {
- /* Better be in decimal dot notation,ie. xx.xx.xx.xx */
- if (isdigit (args[0]) && strchr (args, '.'))
- {
- j = 4;
- while (j)
- {
- memset (buf, 0, 10);
- i = 0;
- while((*args) && (*args != '.'))
- {
- buf[i] = *args++;
- i++;
- }
- if (i)
- {
- val = (int) strtol (buf, NULL, 10);
-
- if (val > 255)
- error ("Invalid IP address");
-
- j--;
- newip |= val << (8 * j);
- args++;
- }
- }
- }
- else
- {
- error ("Invalid host name/address");
- }
- nrom_ipaddr = newip;
- }
-}
-
-static void
-nrom_set_load_port (args, fromtty)
- char *args;
- int fromtty;
-{
- load_port = (int) strtol (args, NULL, 10);
-}
-
-static void
-nrom_set_target_port (args, from_tty)
- char *args;
- int from_tty;
-{
- target_port = (int) strtol (args, NULL, 10);
-}
-
-static void
-nrom_set_control_port (args, fromtty)
- char *args;
- int fromtty;
-{
- control_port = (int) strtol (args, NULL, 10);
-}
-
-static void
-nrom_show_status (args,from_tty)
- char *args;
- int from_tty;
-{
- unsigned char *i;
-
- i = (unsigned char *)&nrom_ipaddr;
-
- printf_filtered ("NetROM target port is %d\n", target_port);
- printf_filtered ("NetROM download port is %d\n", load_port);
- printf_filtered ("NetROM debug control port is %d\n", control_port);
-
- printf_filtered ("NetROM IP Address is %d.%d.%d.%d\n",
- UC(i[0]), UC(i[1]), UC(i[2]), UC(i[3]));
- if (nrom_filetype == BINARY_FTYPE)
- printf_filtered ("download filetype is binary\n");
- else if (nrom_filetype == MOTO_SREC)
- printf_filtered ("download filetype is moto-srec\n");
- else if (nrom_filetype == INTEL_HEX)
- printf_filtered ("download filetype is intel-hex\n");
+ if (load_desc)
+ SERIAL_CLOSE (load_desc);
+ if (ctrl_desc)
+ SERIAL_CLOSE (ctrl_desc);
}
/* Pass arguments directly to the NetROM. */
static void
-nrom_passthru (args, fromtty)
- char *args;
- int fromtty;
+nrom_passthru (char *args, int fromtty)
{
char buf[1024];
- sprintf(buf, "%s\n", args);
- if (nrom_control_send (buf, strlen (buf)) < 0)
+ sprintf (buf, "%s\n", args);
+ if (SERIAL_WRITE (ctrl_desc, buf, strlen (buf)))
error ("nrom_reset: control_send() of `%s'failed", args);
}
-static void
-nrom_store_registers (regno)
-int regno;
-{
- char buf[NROM_BUF_SIZE];
- int i;
- char *p;
-
- p = buf;
- for (i = 0; i < REGISTER_BYTES; i++)
- {
- *p++ = tohex ((registers[i] >> 4) & 0xf);
- *p++ = tohex (registers[i] & 0xf);
- }
- *p = '\0';
- nrom_send (GDB_WRITE_REGS, buf, REGISTER_BYTES * 2, 0, REGISTER_BYTES * 2,
- buf);
-}
-
-static int
-nrom_xfer_inferior_memory (memaddr, myaddr, len, write, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int write;
- struct target_ops *target;
-{
- if (write)
- return nrom_write_inferior_memory (memaddr, myaddr, len);
- else
- return nrom_read_inferior_memory (memaddr, myaddr, len);
-}
-
-/* Copy LEN bytes of data from debugger memory at MYADDR
- to inferior's memory at MEMADDR. Returns errno value. */
-
-static int
-nrom_write_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
-{
- char buf[NROM_BUF_SIZE],obuf[NROM_BUF_SIZE];
- int i;
- char *p;
-
- p = obuf;
- for (i = 0; i < len; i++)
- {
- *p++ = tohex ((myaddr[i] >> 4) & 0xf);
- *p++ = tohex (myaddr[i] & 0xf);
- }
- *p = '\0';
- nrom_send (GDB_WRITE_MEM, obuf, len * 2, memaddr, len, buf);
-
- return len;
-}
-
-/* Read LEN bytes from inferior memory at MEMADDR. Put the result
- at debugger address MYADDR. Returns errno value. */
-
-static int
-nrom_read_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
-{
- char buf[NROM_BUF_SIZE];
-
- nrom_send (GDB_READ_MEM, NULL, 0, memaddr, len, buf);
- memcpy (myaddr, buf, len);
- return len;
-}
-
static void
-nrom_files_info (ignore)
- struct target_ops *ignore;
+nrom_mourn (void)
{
-}
-
-static void
-nrom_mourn()
-{
unpush_target (&nrom_ops);
generic_mourn_inferior ();
}
-/* Convert a packet into its parts and verify check sum. */
-
-static int
-parse_pkt (pkt, hdr, data)
- unsigned char *pkt;
- GPKTHDR *hdr;
- char *data;
-{
- unsigned char xcsum;
- unsigned char *dptr;
-
- /* Build packet header from received data. */
- hex2mem (pkt, (char *) hdr, sizeof(GPKTHDR));
- if (remote_debug > 1)
- {
- printf_filtered ("Packet received: csum = %x,seq number = %x,len = %d\n",
- hdr->csum,hdr->seq_num,hdr->len);
- printf_filtered ("cmd = %x,addr = %x,datalen = %d\n",
- hdr->cmd,hdr->addr,hdr->datalen);
- }
- /* Skip first two bytes of packet when computing checksum. */
- dptr = (sizeof(GPKTHDR) * 2) + pkt;
- pkt += 2;
- if (remote_debug > 1)
- {
- printf_filtered ("Computing checksum over pkt %s\n",pkt);
- printf_filtered ("Of length %d\n",strlen(pkt));
- }
- xcsum = compute_csum (pkt, strlen (pkt));
- if (xcsum != hdr->csum)
- {
- if (remote_debug)
- printf_filtered ("Checksum failure: computed %x, received %x\n",xcsum,
- hdr->csum);
- return (-1);
- }
-
- /* Copy data portion to callers data buffer converting from ASCII
- to data as we go. */
- hex2mem (dptr, data, hdr->datalen);
- return 0;
-}
-
-static int
-read_pkt (pkt)
- char *pkt;
-{
- int n, tries;
- struct sockaddr_in from;
- int from_len = sizeof(from);
- int gotstart;
- int total_len;
- char *p;
-
- p = pkt;
- total_len = 0;
- gotstart = 0;
-
- while (1)
- {
- /* Don't let us get wedged if the target is losing. */
- QUIT;
-
- if (bufdata == 0)
- {
- bufindex = 0;
- n = NROM_BUF_SIZE;
- /* Perform read on socket. This will wait. */
- bufdata = recvfrom (nrom_targ_sock, readbuf, n, 0, &from, &from_len);
- if (bufdata < 0)
- {
- printf_filtered ("Error on socket read of %d\n",errno);
- return (-1);
- }
- if (remote_debug > 2)
- {
- readbuf[bufdata] = '\0';
- printf_filtered ("Received %d bytes. Data is %s\n",
- bufdata, readbuf);
- }
- }
-
- /* skip stuff between packets */
- while (gotstart == 0 && bufdata != 0
- && readbuf[bufindex] != GDB_START_DELIMITER)
- {
- bufdata--;
- bufindex++;
- }
-
- /* look for a start if we haven't seen one */
- if (gotstart == 0 && bufdata != 0
- && readbuf[bufindex] == GDB_START_DELIMITER)
- {
- gotstart = 1;
- bufindex++;
- bufdata--;
- }
-
- /* copy packet data */
- if (gotstart != 0)
- {
- while (bufdata && readbuf[bufindex] != GDB_END_DELIMITER)
- {
- *p = readbuf[bufindex];
- p++;
- bufdata--;
- bufindex++;
- total_len++;
- if (total_len > NROM_BUF_SIZE)
- {
- error ("read_pkt: packet length exceeds %d\n",
- NROM_BUF_SIZE);
- return (-1);
- }
- }
- *p = '\0';
- if (remote_debug > 2)
- printf_filtered ("Packet is '%s'\n", pkt);
- }
+/* Define the target vector. */
- /* Make sure this is the end of the packet. */
- if (gotstart != 0 && bufdata != 0
- && readbuf[bufindex] == GDB_END_DELIMITER)
- {
- gotstart = 0;
- bufindex++;
- bufdata--;
- /* Ensure that the packet is terminated. */
- *p = '\0';
- if (remote_debug > 2)
- printf_filtered ("Returning '%s'\n", pkt);
- return 0;
- }
- }
-}
+struct target_ops nrom_ops;
static void
-send_query_cmd ()
-{
- while (send_pkt (GDB_QUERY_CMD, NULL, 0, 0, 0) < 0)
- ;
-}
-
-static int
-send_pkt (cmd, data, datalen, addr, len)
- int cmd;
- char *data;
- int datalen;
- long addr;
- int len;
-{
- char c[2];
- unsigned char seq;
- struct sockaddr_in mysin;
- int send_cnt;
-
- while (1)
- {
- /* Get a sequence number for this packet. */
- seq = get_seq_number ();
- /* Build the packet. */
- build_pkt (cmd, data, datalen, workbuf, addr, len, seq);
- /* Put delimiters around the pkt. */
- memset (sendbuf, 0, NROM_BUF_SIZE);
- sendbuf[0] = GDB_START_DELIMITER;
- strcat (sendbuf, workbuf);
- c[0] = GDB_END_DELIMITER;
- c[1] = '\0';
- strcat (sendbuf, c);
-
- /* Send the packet out on our socket. */
- if (remote_debug > 1)
- printf_filtered ("Sending pkt: %s\n", sendbuf);
- mysin.sin_family = AF_INET;
- mysin.sin_port = target_port;
- mysin.sin_addr.S_un.S_addr = nrom_ipaddr;
-
- send_cnt = 0;
- while (send_cnt < MAX_SEND_ATTEMPTS)
- {
- if (sendto (nrom_targ_sock, sendbuf, strlen(sendbuf), 0, &mysin,
- sizeof(struct sockaddr_in)) < 0)
- {
- printf_filtered ("sendto error of %d\n", errno);
- send_cnt++;
- }
- else
- break;
- }
- if (send_cnt >= MAX_SEND_ATTEMPTS)
- {
- printf_filtered ("Socket send failed after %d tries\n",
- MAX_SEND_ATTEMPTS);
- return (-1);
- }
- return 1;
- }
-}
-
-/* Convert number NIB to a hex digit. */
-
-static int
-tohex (nib)
- int nib;
-{
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
+init_nrom_ops (void)
+{
+ nrom_ops.to_shortname = "nrom";
+ nrom_ops.to_longname = "Remote XDI `NetROM' target";
+ nrom_ops.to_doc = "Remote debug using a NetROM over Ethernet";
+ nrom_ops.to_open = nrom_open;
+ nrom_ops.to_close = nrom_close;
+ nrom_ops.to_attach = NULL;
+ nrom_ops.to_post_attach = NULL;
+ nrom_ops.to_require_attach = NULL;
+ nrom_ops.to_detach = NULL;
+ nrom_ops.to_require_detach = NULL;
+ nrom_ops.to_resume = NULL;
+ nrom_ops.to_wait = NULL;
+ nrom_ops.to_post_wait = NULL;
+ nrom_ops.to_fetch_registers = NULL;
+ nrom_ops.to_store_registers = NULL;
+ nrom_ops.to_prepare_to_store = NULL;
+ nrom_ops.to_xfer_memory = NULL;
+ nrom_ops.to_files_info = NULL;
+ nrom_ops.to_insert_breakpoint = NULL;
+ nrom_ops.to_remove_breakpoint = NULL;
+ nrom_ops.to_terminal_init = NULL;
+ nrom_ops.to_terminal_inferior = NULL;
+ nrom_ops.to_terminal_ours_for_output = NULL;
+ nrom_ops.to_terminal_ours = NULL;
+ nrom_ops.to_terminal_info = NULL;
+ nrom_ops.to_kill = nrom_kill;
+ nrom_ops.to_load = nrom_load;
+ nrom_ops.to_lookup_symbol = NULL;
+ nrom_ops.to_create_inferior = NULL;
+ nrom_ops.to_post_startup_inferior = NULL;
+ nrom_ops.to_acknowledge_created_inferior = NULL;
+ nrom_ops.to_clone_and_follow_inferior = NULL;
+ nrom_ops.to_post_follow_inferior_by_clone = NULL;
+ nrom_ops.to_insert_fork_catchpoint = NULL;
+ nrom_ops.to_remove_fork_catchpoint = NULL;
+ nrom_ops.to_insert_vfork_catchpoint = NULL;
+ nrom_ops.to_remove_vfork_catchpoint = NULL;
+ nrom_ops.to_has_forked = NULL;
+ nrom_ops.to_has_vforked = NULL;
+ nrom_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ nrom_ops.to_post_follow_vfork = NULL;
+ nrom_ops.to_insert_exec_catchpoint = NULL;
+ nrom_ops.to_remove_exec_catchpoint = NULL;
+ nrom_ops.to_has_execd = NULL;
+ nrom_ops.to_reported_exec_events_per_exec_call = NULL;
+ nrom_ops.to_has_exited = NULL;
+ nrom_ops.to_mourn_inferior = nrom_mourn;
+ nrom_ops.to_can_run = NULL;
+ nrom_ops.to_notice_signals = 0;
+ nrom_ops.to_thread_alive = 0;
+ nrom_ops.to_stop = 0;
+ nrom_ops.to_pid_to_exec_file = NULL;
+ nrom_ops.to_stratum = download_stratum;
+ nrom_ops.DONT_USE = NULL;
+ nrom_ops.to_has_all_memory = 1;
+ nrom_ops.to_has_memory = 1;
+ nrom_ops.to_has_stack = 1;
+ nrom_ops.to_has_registers = 1;
+ nrom_ops.to_has_execution = 0;
+ nrom_ops.to_sections = NULL;
+ nrom_ops.to_sections_end = NULL;
+ nrom_ops.to_magic = OPS_MAGIC;
}
-/* snatched from Stevens, pp279+ */
-
-int
-writen (sock, ptr, nbytes)
- int sock;
- char *ptr;
- int nbytes;
-{
- int nleft, nwritten;
- char *buf = ptr;
-
- nleft = nbytes;
- while (nleft > 0)
- {
- nwritten = write (sock, buf, nleft);
- if (nwritten <= 0)
- return nwritten;
- nleft -= nwritten;
- buf += nwritten;
- }
- return (nbytes - nleft);
-}
-
-/* Define the target vector. */
-
-struct target_ops nrom_ops = {
- "nrom", /* to_shortname */
- "Remote XDI `NetROM' target", /* to_longname */
- "Remote debug using a NetROM over Ethernet",
- nrom_open, /* to_open */
- nrom_close,
- nrom_attach,
- nrom_detach,
- nrom_resume,
- nrom_wait, /* to_wait */
- nrom_fetch_registers, /* to_fetch_registers */
- nrom_store_registers, /* to_store_registers */
- nrom_prepare_to_store, /* to_prepare_to_store */
- nrom_xfer_inferior_memory, /* to_xfer_memory */
- nrom_files_info, /* to_files_info */
- NULL, /* to_insert_breakpoint */
- NULL, /* to_remove_breakpoint */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- nrom_kill,
- nrom_load,
- NULL,
- nrom_create_inferior, /* to_create_inferior */
- nrom_mourn,
- nrom_can_run,
- 0, /* to_notice_signals */
- 0,
- process_stratum, /* to_stratum */
- NULL, /* to_next */
- 1,
- 1,
- 1,
- 1,
- 0, /* to_has_execution */
- NULL, /* sections */
- NULL, /* sections_end */
- OPS_MAGIC /* to_magic */
-};
-
void
-_initialize_remote_nrom ()
+_initialize_remote_nrom (void)
{
+ init_nrom_ops ();
add_target (&nrom_ops);
- /* Add some commands for helpers. */
- add_cmd ("nrom_ipaddr", no_class, nrom_set_ipaddr,
- "Set the IP Address of the NetROM\n",
- &setlist);
- add_cmd ("target_port", no_class, nrom_set_target_port,
- "Set the Port to use for NetROM target communication\n",
- &setlist);
- add_cmd ("load_port", no_class, nrom_set_load_port,
- "Set the Port to use for NetROM downloads\n",
- &setlist);
- add_cmd ("control_port", no_class, nrom_set_control_port,
- "Set the Port to use for NetROM debugger services\n",
- &setlist);
- add_cmd ("nrom_filetype", no_class, nrom_set_filetype,
- "Set the filetype to use on NetROM downloads",
- &setlist);
-
- add_cmd ("nrom", no_class, nrom_show_status,
- "Show the current NetROM status\n",
- &showlist);
+ add_show_from_set (
+ add_set_cmd ("nrom_load_port", no_class, var_zinteger, (char *) &load_port,
+ "Set the port to use for NetROM downloads\n", &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("nrom_control_port", no_class, var_zinteger, (char *) &control_port,
+ "Set the port to use for NetROM debugger services\n", &setlist),
+ &showlist);
add_cmd ("nrom", no_class, nrom_passthru,
"Pass arguments as command to NetROM",