summaryrefslogtreecommitdiffstats
path: root/u-boot/tools/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'u-boot/tools/gdb')
-rw-r--r--u-boot/tools/gdb/Makefile74
-rw-r--r--u-boot/tools/gdb/error.c81
-rw-r--r--u-boot/tools/gdb/error.h30
-rw-r--r--u-boot/tools/gdb/gdbcont.c87
-rw-r--r--u-boot/tools/gdb/gdbsend.c137
-rw-r--r--u-boot/tools/gdb/remote.c928
-rw-r--r--u-boot/tools/gdb/remote.h28
-rw-r--r--u-boot/tools/gdb/serial.c149
-rw-r--r--u-boot/tools/gdb/serial.h34
9 files changed, 1548 insertions, 0 deletions
diff --git a/u-boot/tools/gdb/Makefile b/u-boot/tools/gdb/Makefile
new file mode 100644
index 0000000..90037c7
--- /dev/null
+++ b/u-boot/tools/gdb/Makefile
@@ -0,0 +1,74 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2000
+# Murray Jensen <Murray.Jensen@csiro.au>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# 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 $(TOPDIR)/config.mk
+
+BINS = gdbsend gdbcont
+
+COBJS = gdbsend.o gdbcont.o error.o remote.o serial.o
+
+HOSTOBJS := $(addprefix $(obj),$(COBJS))
+HOSTSRCS := $(COBJS:.o=.c)
+BINS := $(addprefix $(obj),$(BINS))
+
+#
+# Use native tools and options
+#
+HOSTCPPFLAGS = -I$(BFD_ROOT_DIR)/include
+
+HOSTOS := $(shell uname -s | sed -e 's/\([Cc][Yy][Gg][Ww][Ii][Nn]\).*/cygwin/')
+
+ifeq ($(HOSTOS),cygwin)
+
+all:
+$(obj).depend:
+
+else # ! CYGWIN
+
+all: $(obj).depend $(BINS)
+
+$(obj)gdbsend: $(obj)gdbsend.o $(obj)error.o $(obj)remote.o $(obj)serial.o
+ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
+$(obj)gdbcont: $(obj)gdbcont.o $(obj)error.o $(obj)remote.o $(obj)serial.o
+ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
+clean:
+ rm -f $(HOSTOBJS)
+
+distclean: clean
+ rm -f $(BINS) $(obj)core $(obj)*.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
+endif # cygwin
diff --git a/u-boot/tools/gdb/error.c b/u-boot/tools/gdb/error.c
new file mode 100644
index 0000000..276a00a
--- /dev/null
+++ b/u-boot/tools/gdb/error.c
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "error.h"
+
+char *pname;
+
+void
+Warning(char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "%s: WARNING: ", pname);
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ fprintf(stderr, "\n");
+}
+
+void
+Error(char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "%s: ERROR: ", pname);
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ fprintf(stderr, "\n");
+
+ exit(1);
+}
+
+void
+Perror(char *fmt, ...)
+{
+ va_list args;
+ int e = errno;
+ char *p;
+
+ fprintf(stderr, "%s: ERROR: ", pname);
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ if ((p = strerror(e)) == NULL || *p == '\0')
+ fprintf(stderr, ": Unknown Error (%d)\n", e);
+ else
+ fprintf(stderr, ": %s\n", p);
+
+ exit(1);
+}
diff --git a/u-boot/tools/gdb/error.h b/u-boot/tools/gdb/error.h
new file mode 100644
index 0000000..0698213
--- /dev/null
+++ b/u-boot/tools/gdb/error.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <stdarg.h>
+
+extern char *pname;
+
+extern void Warning(char *, ...);
+extern void Error(char *, ...);
+extern void Perror(char *, ...);
diff --git a/u-boot/tools/gdb/gdbcont.c b/u-boot/tools/gdb/gdbcont.c
new file mode 100644
index 0000000..300545d
--- /dev/null
+++ b/u-boot/tools/gdb/gdbcont.c
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "serial.h"
+#include "error.h"
+#include "remote.h"
+
+char *serialdev = "/dev/term/b";
+speed_t speed = B230400;
+int verbose = 0;
+
+int
+main(int ac, char **av)
+{
+ int c, sfd;
+
+ if ((pname = strrchr(av[0], '/')) == NULL)
+ pname = av[0];
+ else
+ pname++;
+
+ while ((c = getopt(ac, av, "b:p:v")) != EOF)
+ switch (c) {
+
+ case 'b':
+ if ((speed = cvtspeed(optarg)) == B0)
+ Error("can't decode baud rate specified in -b option");
+ break;
+
+ case 'p':
+ serialdev = optarg;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ default:
+ usage:
+ fprintf(stderr, "Usage: %s [-b bps] [-p dev] [-v]\n", pname);
+ exit(1);
+ }
+ if (optind != ac)
+ goto usage;
+
+ if (verbose)
+ fprintf(stderr, "Opening serial port and sending continue...\n");
+
+ if ((sfd = serialopen(serialdev, speed)) < 0)
+ Perror("open of serial device '%s' failed", serialdev);
+
+ remote_desc = sfd;
+ remote_reset();
+ remote_continue();
+
+ if (serialclose(sfd) < 0)
+ Perror("close of serial device '%s' failed", serialdev);
+
+ if (verbose)
+ fprintf(stderr, "Done.\n");
+
+ return (0);
+}
diff --git a/u-boot/tools/gdb/gdbsend.c b/u-boot/tools/gdb/gdbsend.c
new file mode 100644
index 0000000..8cd8347
--- /dev/null
+++ b/u-boot/tools/gdb/gdbsend.c
@@ -0,0 +1,137 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "serial.h"
+#include "error.h"
+#include "remote.h"
+
+char *serialdev = "/dev/term/b";
+speed_t speed = B230400;
+int verbose = 0, docont = 0;
+unsigned long addr = 0x10000UL;
+
+int
+main(int ac, char **av)
+{
+ int c, sfd, ifd;
+ char *ifn, *image;
+ struct stat ist;
+
+ if ((pname = strrchr(av[0], '/')) == NULL)
+ pname = av[0];
+ else
+ pname++;
+
+ while ((c = getopt(ac, av, "a:b:cp:v")) != EOF)
+ switch (c) {
+
+ case 'a': {
+ char *ep;
+
+ addr = strtol(optarg, &ep, 0);
+ if (ep == optarg || *ep != '\0')
+ Error("can't decode address specified in -a option");
+ break;
+ }
+
+ case 'b':
+ if ((speed = cvtspeed(optarg)) == B0)
+ Error("can't decode baud rate specified in -b option");
+ break;
+
+ case 'c':
+ docont = 1;
+ break;
+
+ case 'p':
+ serialdev = optarg;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ default:
+ usage:
+ fprintf(stderr,
+ "Usage: %s [-a addr] [-b bps] [-c] [-p dev] [-v] imagefile\n",
+ pname);
+ exit(1);
+ }
+
+ if (optind != ac - 1)
+ goto usage;
+ ifn = av[optind++];
+
+ if (verbose)
+ fprintf(stderr, "Opening file and reading image...\n");
+
+ if ((ifd = open(ifn, O_RDONLY)) < 0)
+ Perror("can't open kernel image file '%s'", ifn);
+
+ if (fstat(ifd, &ist) < 0)
+ Perror("fstat '%s' failed", ifn);
+
+ if ((image = (char *)malloc(ist.st_size)) == NULL)
+ Perror("can't allocate %ld bytes for image", ist.st_size);
+
+ if ((c = read(ifd, image, ist.st_size)) < 0)
+ Perror("read of %d bytes from '%s' failed", ist.st_size, ifn);
+
+ if (c != ist.st_size)
+ Error("read of %ld bytes from '%s' failed (%d)", ist.st_size, ifn, c);
+
+ if (close(ifd) < 0)
+ Perror("close of '%s' failed", ifn);
+
+ if (verbose)
+ fprintf(stderr, "Opening serial port and sending image...\n");
+
+ if ((sfd = serialopen(serialdev, speed)) < 0)
+ Perror("open of serial device '%s' failed", serialdev);
+
+ remote_desc = sfd;
+ remote_reset();
+ remote_write_bytes(addr, image, ist.st_size);
+
+ if (docont) {
+ if (verbose)
+ fprintf(stderr, "[continue]");
+ remote_continue();
+ }
+
+ if (serialclose(sfd) < 0)
+ Perror("close of serial device '%s' failed", serialdev);
+
+ if (verbose)
+ fprintf(stderr, "Done.\n");
+
+ return (0);
+}
diff --git a/u-boot/tools/gdb/remote.c b/u-boot/tools/gdb/remote.c
new file mode 100644
index 0000000..c76a7ba
--- /dev/null
+++ b/u-boot/tools/gdb/remote.c
@@ -0,0 +1,928 @@
+/*
+ * taken from gdb/remote.c
+ *
+ * I am only interested in the write to memory stuff - everything else
+ * has been ripped out
+ *
+ * all the copyright notices etc have been left in
+ */
+
+/* enough so that it will compile */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*nicked from gcc..*/
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void* alloca(size_t);
+#ifdef __cplusplus
+}
+#endif
+#endif /* alloca not defined. */
+
+
+#include "serial.h"
+#include "error.h"
+#include "remote.h"
+#define REGISTER_BYTES 0
+#define fprintf_unfiltered fprintf
+#define fprintf_filtered fprintf
+#define fputs_unfiltered fputs
+#define fputs_filtered fputs
+#define fputc_unfiltered fputc
+#define fputc_filtered fputc
+#define printf_unfiltered printf
+#define printf_filtered printf
+#define puts_unfiltered puts
+#define puts_filtered puts
+#define putchar_unfiltered putchar
+#define putchar_filtered putchar
+#define fputstr_unfiltered(a,b,c) fputs((a), (c))
+#define gdb_stdlog stderr
+#define SERIAL_READCHAR(fd,timo) serialreadchar((fd), (timo))
+#define SERIAL_WRITE(fd, addr, len) serialwrite((fd), (addr), (len))
+#define error Error
+#define perror_with_name Perror
+#define gdb_flush fflush
+#define max(a,b) (((a)>(b))?(a):(b))
+#define min(a,b) (((a)<(b))?(a):(b))
+#define target_mourn_inferior() {}
+#define ULONGEST unsigned long
+#define CORE_ADDR unsigned long
+
+static int putpkt (char *);
+static int putpkt_binary(char *, int);
+static void getpkt (char *, int);
+
+static int remote_debug = 0, remote_register_buf_size = 0, watchdog = 0;
+
+int remote_desc = -1, remote_timeout = 10;
+
+static void
+fputstrn_unfiltered(char *s, int n, int x, FILE *fp)
+{
+ while (n-- > 0)
+ fputc(*s++, fp);
+}
+
+void
+remote_reset(void)
+{
+ SERIAL_WRITE(remote_desc, "+", 1);
+}
+
+void
+remote_continue(void)
+{
+ putpkt("c");
+}
+
+/* Remote target communications for serial-line targets in custom GDB protocol
+ Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+ 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 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+/* *INDENT-OFF* */
+/* Remote communication protocol.
+
+ A debug packet whose contents are <data>
+ is encapsulated for transmission in the form:
+
+ $ <data> # CSUM1 CSUM2
+
+ <data> must be ASCII alphanumeric and cannot include characters
+ '$' or '#'. If <data> starts with two characters followed by
+ ':', then the existing stubs interpret this as a sequence number.
+
+ CSUM1 and CSUM2 are ascii hex representation of an 8-bit
+ checksum of <data>, the most significant nibble is sent first.
+ the hex digits 0-9,a-f are used.
+
+ Receiver responds with:
+
+ + - if CSUM is correct and ready for next packet
+ - - if CSUM is incorrect
+
+ <data> is as follows:
+ Most values are encoded in ascii hex digits. Signal numbers are according
+ to the numbering in target.h.
+
+ Request Packet
+
+ set thread Hct... Set thread for subsequent operations.
+ c = 'c' for thread used in step and
+ continue; t... can be -1 for all
+ threads.
+ c = 'g' for thread used in other
+ operations. If zero, pick a thread,
+ any thread.
+ reply OK for success
+ ENN for an error.
+
+ read registers g
+ reply XX....X Each byte of register data
+ is described by two hex digits.
+ Registers are in the internal order
+ for GDB, and the bytes in a register
+ are in the same order the machine uses.
+ or ENN for an error.
+
+ write regs GXX..XX Each byte of register data
+ is described by two hex digits.
+ reply OK for success
+ ENN for an error
+
+ write reg Pn...=r... Write register n... with value r...,
+ which contains two hex digits for each
+ byte in the register (target byte
+ order).
+ reply OK for success
+ ENN for an error
+ (not supported by all stubs).
+
+ read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
+ reply XX..XX XX..XX is mem contents
+ Can be fewer bytes than requested
+ if able to read only part of the data.
+ or ENN NN is errno
+
+ write mem MAA..AA,LLLL:XX..XX
+ AA..AA is address,
+ LLLL is number of bytes,
+ XX..XX is data
+ reply OK for success
+ ENN for an error (this includes the case
+ where only part of the data was
+ written).
+
+ write mem XAA..AA,LLLL:XX..XX
+ (binary) AA..AA is address,
+ LLLL is number of bytes,
+ XX..XX is binary data
+ reply OK for success
+ ENN for an error
+
+ continue cAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ step sAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ continue with Csig;AA..AA Continue with signal sig (hex signal
+ signal number). If ;AA..AA is omitted,
+ resume at same address.
+
+ step with Ssig;AA..AA Like 'C' but step not continue.
+ signal
+
+ last signal ? Reply the current reason for stopping.
+ This is the same reply as is generated
+ for step or cont : SAA where AA is the
+ signal number.
+
+ detach D Reply OK.
+
+ There is no immediate reply to step or cont.
+ The reply comes when the machine stops.
+ It is SAA AA is the signal number.
+
+ or... TAAn...:r...;n...:r...;n...:r...;
+ AA = signal number
+ n... = register number (hex)
+ r... = register contents
+ n... = `thread'
+ r... = thread process ID. This is
+ a hex integer.
+ n... = other string not starting
+ with valid hex digit.
+ gdb should ignore this n,r pair
+ and go on to the next. This way
+ we can extend the protocol.
+ or... WAA The process exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ or... XAA The process terminated with signal
+ AA.
+ or (obsolete) NAA;tttttttt;dddddddd;bbbbbbbb
+ AA = signal number
+ tttttttt = address of symbol "_start"
+ dddddddd = base of data section
+ bbbbbbbb = base of bss section.
+ Note: only used by Cisco Systems
+ targets. The difference between this
+ reply and the "qOffsets" query is that
+ the 'N' packet may arrive spontaneously
+ whereas the 'qOffsets' is a query
+ initiated by the host debugger.
+ or... OXX..XX XX..XX is hex encoding of ASCII data. This
+ can happen at any time while the
+ program is running and the debugger
+ should continue to wait for
+ 'W', 'T', etc.
+
+ thread alive TXX Find out if the thread XX is alive.
+ reply OK thread is still alive
+ ENN thread is dead
+
+ remote restart RXX Restart the remote server
+
+ extended ops ! Use the extended remote protocol.
+ Sticky -- only needs to be set once.
+
+ kill request k
+
+ toggle debug d toggle debug flag (see 386 & 68k stubs)
+ reset r reset -- see sparc stub.
+ reserved <other> On other requests, the stub should
+ ignore the request and send an empty
+ response ($#<checksum>). This way
+ we can extend the protocol and GDB
+ can tell whether the stub it is
+ talking to uses the old or the new.
+ search tAA:PP,MM Search backwards starting at address
+ AA for a match with pattern PP and
+ mask MM. PP and MM are 4 bytes.
+ Not supported by all stubs.
+
+ general query qXXXX Request info about XXXX.
+ general set QXXXX=yyyy Set value of XXXX to yyyy.
+ query sect offs qOffsets Get section offsets. Reply is
+ Text=xxx;Data=yyy;Bss=zzz
+
+ Responses can be run-length encoded to save space. A '*' means that
+ the next character is an ASCII encoding giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ The encoding is n+29, yielding a printable character where n >=3
+ (which is where rle starts to win). Don't use an n > 126.
+
+ So
+ "0* " means the same as "0000". */
+/* *INDENT-ON* */
+
+/* This variable (available to the user via "set remotebinarydownload")
+ dictates whether downloads are sent in binary (via the 'X' packet).
+ We assume that the stub can, and attempt to do it. This will be cleared if
+ the stub does not understand it. This switch is still needed, though
+ in cases when the packet is supported in the stub, but the connection
+ does not allow it (i.e., 7-bit serial connection only). */
+static int remote_binary_download = 1;
+
+/* Have we already checked whether binary downloads work? */
+static int remote_binary_checked;
+
+/* Maximum number of bytes to read/write at once. The value here
+ is chosen to fill up a packet (the headers account for the 32). */
+#define MAXBUFBYTES(N) (((N)-32)/2)
+
+/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
+ and i386-stub.c. Normally, no one would notice because it only matters
+ for writing large chunks of memory (e.g. in downloads). Also, this needs
+ to be more than 400 if required to hold the registers (see below, where
+ we round it up based on REGISTER_BYTES). */
+/* Round up PBUFSIZ to hold all the registers, at least. */
+#define PBUFSIZ ((REGISTER_BYTES > MAXBUFBYTES (400)) \
+ ? (REGISTER_BYTES * 2 + 32) \
+ : 400)
+
+
+/* This variable sets the number of bytes to be written to the target
+ in a single packet. Normally PBUFSIZ is satisfactory, but some
+ targets need smaller values (perhaps because the receiving end
+ is slow). */
+
+static int remote_write_size = 0x7fffffff;
+
+/* This variable sets the number of bits in an address that are to be
+ sent in a memory ("M" or "m") packet. Normally, after stripping
+ leading zeros, the entire address would be sent. This variable
+ restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The
+ initial implementation of remote.c restricted the address sent in
+ memory packets to ``host::sizeof long'' bytes - (typically 32
+ bits). Consequently, for 64 bit targets, the upper 32 bits of an
+ address was never sent. Since fixing this bug may cause a break in
+ some remote targets this variable is principly provided to
+ facilitate backward compatibility. */
+
+static int remote_address_size;
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (int a)
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ else {
+ error ("Reply contains invalid hex digit %d", a);
+ return -1;
+ }
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (int nib)
+{
+ if (nib < 10)
+ return '0' + nib;
+ else
+ return 'a' + nib - 10;
+}
+
+/* Return the number of hex digits in num. */
+
+static int
+hexnumlen (ULONGEST num)
+{
+ int i;
+
+ for (i = 0; num != 0; i++)
+ num >>= 4;
+
+ return max (i, 1);
+}
+
+/* Set BUF to the hex digits representing NUM. */
+
+static int
+hexnumstr (char *buf, ULONGEST num)
+{
+ int i;
+ int len = hexnumlen (num);
+
+ buf[len] = '\0';
+
+ for (i = len - 1; i >= 0; i--)
+ {
+ buf[i] = "0123456789abcdef"[(num & 0xf)];
+ num >>= 4;
+ }
+
+ return len;
+}
+
+/* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
+
+static CORE_ADDR
+remote_address_masked (CORE_ADDR addr)
+{
+ if (remote_address_size > 0
+ && remote_address_size < (sizeof (ULONGEST) * 8))
+ {
+ /* Only create a mask when that mask can safely be constructed
+ in a ULONGEST variable. */
+ ULONGEST mask = 1;
+ mask = (mask << remote_address_size) - 1;
+ addr &= mask;
+ }
+ return addr;
+}
+
+/* Determine whether the remote target supports binary downloading.
+ This is accomplished by sending a no-op memory write of zero length
+ to the target at the specified address. It does not suffice to send
+ the whole packet, since many stubs strip the eighth bit and subsequently
+ compute a wrong checksum, which causes real havoc with remote_write_bytes.
+
+ NOTE: This can still lose if the serial line is not eight-bit clean. In
+ cases like this, the user should clear "remotebinarydownload". */
+static void
+check_binary_download (CORE_ADDR addr)
+{
+ if (remote_binary_download && !remote_binary_checked)
+ {
+ char *buf = alloca (PBUFSIZ);
+ char *p;
+ remote_binary_checked = 1;
+
+ p = buf;
+ *p++ = 'X';
+ p += hexnumstr (p, (ULONGEST) addr);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) 0);
+ *p++ = ':';
+ *p = '\0';
+
+ putpkt_binary (buf, (int) (p - buf));
+ getpkt (buf, 0);
+
+ if (buf[0] == '\0')
+ remote_binary_download = 0;
+ }
+
+ if (remote_debug)
+ {
+ if (remote_binary_download)
+ fprintf_unfiltered (gdb_stdlog,
+ "binary downloading suppported by target\n");
+ else
+ fprintf_unfiltered (gdb_stdlog,
+ "binary downloading NOT suppported by target\n");
+ }
+}
+
+/* Write memory data directly to the remote machine.
+ This does not inform the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+int
+remote_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned char *buf = alloca (PBUFSIZ);
+ int max_buf_size; /* Max size of packet output buffer */
+ int origlen;
+ extern int verbose;
+
+ /* Verify that the target can support a binary download */
+ check_binary_download (memaddr);
+
+ /* Chop the transfer down if necessary */
+
+ max_buf_size = min (remote_write_size, PBUFSIZ);
+ if (remote_register_buf_size != 0)
+ max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+ /* Subtract header overhead from max payload size - $M<memaddr>,<len>:#nn */
+ max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4;
+
+ origlen = len;
+ while (len > 0)
+ {
+ unsigned char *p, *plen;
+ int todo;
+ int i;
+
+ /* construct "M"<memaddr>","<len>":" */
+ /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
+ memaddr = remote_address_masked (memaddr);
+ p = buf;
+ if (remote_binary_download)
+ {
+ *p++ = 'X';
+ todo = min (len, max_buf_size);
+ }
+ else
+ {
+ *p++ = 'M';
+ todo = min (len, max_buf_size / 2); /* num bytes that will fit */
+ }
+
+ p += hexnumstr ((char *)p, (ULONGEST) memaddr);
+ *p++ = ',';
+
+ plen = p; /* remember where len field goes */
+ p += hexnumstr ((char *)p, (ULONGEST) todo);
+ *p++ = ':';
+ *p = '\0';
+
+ /* We send target system values byte by byte, in increasing byte
+ addresses, each byte encoded as two hex characters (or one
+ binary character). */
+ if (remote_binary_download)
+ {
+ int escaped = 0;
+ for (i = 0;
+ (i < todo) && (i + escaped) < (max_buf_size - 2);
+ i++)
+ {
+ switch (myaddr[i] & 0xff)
+ {
+ case '$':
+ case '#':
+ case 0x7d:
+ /* These must be escaped */
+ escaped++;
+ *p++ = 0x7d;
+ *p++ = (myaddr[i] & 0xff) ^ 0x20;
+ break;
+ default:
+ *p++ = myaddr[i] & 0xff;
+ break;
+ }
+ }
+
+ if (i < todo)
+ {
+ /* Escape chars have filled up the buffer prematurely,
+ and we have actually sent fewer bytes than planned.
+ Fix-up the length field of the packet. */
+
+ /* FIXME: will fail if new len is a shorter string than
+ old len. */
+
+ plen += hexnumstr ((char *)plen, (ULONGEST) i);
+ *plen++ = ':';
+ }
+ }
+ else
+ {
+ for (i = 0; i < todo; i++)
+ {
+ *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+ *p++ = tohex (myaddr[i] & 0xf);
+ }
+ *p = '\0';
+ }
+
+ putpkt_binary ((char *)buf, (int) (p - buf));
+ getpkt ((char *)buf, 0);
+
+ if (buf[0] == 'E')
+ {
+ /* There is no correspondance between what the remote protocol uses
+ for errors and errno codes. We would like a cleaner way of
+ representing errors (big enough to include errno codes, bfd_error
+ codes, and others). But for now just return EIO. */
+ errno = EIO;
+ return 0;
+ }
+
+ /* Increment by i, not by todo, in case escape chars
+ caused us to send fewer bytes than we'd planned. */
+ myaddr += i;
+ memaddr += i;
+ len -= i;
+
+ if (verbose)
+ putc('.', stderr);
+ }
+ return origlen;
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+ See comment at top of file for details. */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (int timeout)
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (remote_desc, timeout);
+
+ switch (ch)
+ {
+ case SERIAL_EOF:
+ error ("Remote connection closed");
+ case SERIAL_ERROR:
+ perror_with_name ("Remote communication error");
+ case SERIAL_TIMEOUT:
+ return ch;
+ default:
+ return ch & 0x7f;
+ }
+}
+
+static int
+putpkt (buf)
+ char *buf;
+{
+ return putpkt_binary (buf, strlen (buf));
+}
+
+/* Send a packet to the remote machine, with error checking. The data
+ of the packet is in BUF. The string in BUF can be at most PBUFSIZ - 5
+ to account for the $, # and checksum, and for a possible /0 if we are
+ debugging (remote_debug) and want to print the sent packet as a string */
+
+static int
+putpkt_binary (buf, cnt)
+ char *buf;
+ int cnt;
+{
+ int i;
+ unsigned char csum = 0;
+ char *buf2 = alloca (PBUFSIZ);
+ char *junkbuf = alloca (PBUFSIZ);
+
+ int ch;
+ int tcount = 0;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (cnt > BUFSIZ - 5) /* Prosanity check */
+ abort ();
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ while (1)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ *p = '\0';
+ fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
+ fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
+ fprintf_unfiltered (gdb_stdlog, "...");
+ gdb_flush (gdb_stdlog);
+ }
+ if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+ perror_with_name ("putpkt: write failed");
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (1)
+ {
+ ch = readchar (remote_timeout);
+
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case SERIAL_TIMEOUT:
+ case '$':
+ if (started_error_output)
+ {
+ putchar_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "Ack\n");
+ return 1;
+ case SERIAL_TIMEOUT:
+ tcount++;
+ if (tcount > 3)
+ return 0;
+ break; /* Retransmit buffer */
+ case '$':
+ {
+ /* It's probably an old response, and we're out of sync.
+ Just gobble up the packet and ignore it. */
+ getpkt (junkbuf, 0);
+ continue; /* Now, go look for + */
+ }
+ default:
+ if (remote_debug)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
+ }
+ fputc_unfiltered (ch & 0177, gdb_stdlog);
+ }
+ continue;
+ }
+ break; /* Here to retransmit */
+ }
+
+#if 0
+ /* This is wrong. If doing a long backtrace, the user should be
+ able to get out next time we call QUIT, without anything as
+ violent as interrupt_query. If we want to provide a way out of
+ here without getting to the next QUIT, it should be based on
+ hitting ^C twice as in remote_wait. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+#endif
+ }
+}
+
+/* Come here after finding the start of the frame. Collect the rest
+ into BUF, verifying the checksum, length, and handling run-length
+ compression. Returns 0 on any error, 1 on success. */
+
+static int
+read_frame (char *buf)
+{
+ unsigned char csum;
+ char *bp;
+ int c;
+
+ csum = 0;
+ bp = buf;
+
+ while (1)
+ {
+ c = readchar (remote_timeout);
+
+ switch (c)
+ {
+ case SERIAL_TIMEOUT:
+ if (remote_debug)
+ fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
+ return 0;
+ case '$':
+ if (remote_debug)
+ fputs_filtered ("Saw new packet start in middle of old one\n",
+ gdb_stdlog);
+ return 0; /* Start a new packet, count retries */
+ case '#':
+ {
+ unsigned char pktcsum;
+
+ *bp = '\000';
+
+ pktcsum = fromhex (readchar (remote_timeout)) << 4;
+ pktcsum |= fromhex (readchar (remote_timeout));
+
+ if (csum == pktcsum)
+ {
+ return 1;
+ }
+
+ if (remote_debug)
+ {
+ fprintf_filtered (gdb_stdlog,
+ "Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+ pktcsum, csum);
+ fputs_filtered (buf, gdb_stdlog);
+ fputs_filtered ("\n", gdb_stdlog);
+ }
+ return 0;
+ }
+ case '*': /* Run length encoding */
+ csum += c;
+ c = readchar (remote_timeout);
+ csum += c;
+ c = c - ' ' + 3; /* Compute repeat count */
+
+ if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
+ {
+ memset (bp, *(bp - 1), c);
+ bp += c;
+ continue;
+ }
+
+ *bp = '\0';
+ printf_filtered ("Repeat count %d too large for buffer: ", c);
+ puts_filtered (buf);
+ puts_filtered ("\n");
+ return 0;
+ default:
+ if (bp < buf + PBUFSIZ - 1)
+ {
+ *bp++ = c;
+ csum += c;
+ continue;
+ }
+
+ *bp = '\0';
+ puts_filtered ("Remote packet too long: ");
+ puts_filtered (buf);
+ puts_filtered ("\n");
+
+ return 0;
+ }
+ }
+}
+
+/* Read a packet from the remote machine, with error checking, and
+ store it in BUF. BUF is expected to be of size PBUFSIZ. If
+ FOREVER, wait forever rather than timing out; this is used while
+ the target is executing user code. */
+
+static void
+getpkt (buf, forever)
+ char *buf;
+ int forever;
+{
+ int c;
+ int tries;
+ int timeout;
+ int val;
+
+ strcpy (buf, "timeout");
+
+ if (forever)
+ {
+ timeout = watchdog > 0 ? watchdog : -1;
+ }
+
+ else
+ timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* This can loop forever if the remote side sends us characters
+ continuously, but if it pauses, we'll get a zero from readchar
+ because of timeout. Then we'll count that as a retry. */
+
+ /* Note that we will only wait forever prior to the start of a packet.
+ After that, we expect characters to arrive at a brisk pace. They
+ should show up within remote_timeout intervals. */
+
+ do
+ {
+ c = readchar (timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (forever) /* Watchdog went off. Kill the target. */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+ if (remote_debug)
+ fputs_filtered ("Timed out.\n", gdb_stdlog);
+ goto retry;
+ }
+ }
+ while (c != '$');
+
+ /* We've found the start of a packet, now collect the data. */
+
+ val = read_frame (buf);
+
+ if (val == 1)
+ {
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Packet received: ");
+ fputstr_unfiltered (buf, 0, gdb_stdlog);
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+ SERIAL_WRITE (remote_desc, "+", 1);
+ return;
+ }
+
+ /* Try the whole thing again. */
+ retry:
+ SERIAL_WRITE (remote_desc, "-", 1);
+ }
+
+ /* We have tried hard enough, and just can't receive the packet. Give up. */
+
+ printf_unfiltered ("Ignoring packet error, continuing...\n");
+ SERIAL_WRITE (remote_desc, "+", 1);
+}
diff --git a/u-boot/tools/gdb/remote.h b/u-boot/tools/gdb/remote.h
new file mode 100644
index 0000000..f14dacb
--- /dev/null
+++ b/u-boot/tools/gdb/remote.h
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+extern int remote_desc, remote_timeout;
+
+extern void remote_reset(void);
+extern void remote_continue(void);
+extern int remote_write_bytes(unsigned long, char *, int);
diff --git a/u-boot/tools/gdb/serial.c b/u-boot/tools/gdb/serial.c
new file mode 100644
index 0000000..2f2e529
--- /dev/null
+++ b/u-boot/tools/gdb/serial.c
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include "serial.h"
+
+#if defined(__sun__) || \
+ defined(__OpenBSD__) || \
+ defined(__FreeBSD__) || \
+ defined(__NetBSD__) || \
+ defined(__APPLE__)
+static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, { 0 } };
+#else
+static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, 0 };
+#endif
+
+static struct speedmap {
+ char *str;
+ speed_t val;
+} speedmap[] = {
+ { "50", B50 }, { "75", B75 }, { "110", B110 },
+ { "134", B134 }, { "150", B150 }, { "200", B200 },
+ { "300", B300 }, { "600", B600 }, { "1200", B1200 },
+ { "1800", B1800 }, { "2400", B2400 }, { "4800", B4800 },
+ { "9600", B9600 }, { "19200", B19200 }, { "38400", B38400 },
+ { "57600", B57600 },
+#ifdef B76800
+ { "76800", B76800 },
+#endif
+ { "115200", B115200 },
+#ifdef B153600
+ { "153600", B153600 },
+#endif
+ { "230400", B230400 },
+#ifdef B307200
+ { "307200", B307200 },
+#endif
+#ifdef B460800
+ { "460800", B460800 }
+#endif
+};
+static int nspeeds = sizeof speedmap / sizeof speedmap[0];
+
+speed_t
+cvtspeed(char *str)
+{
+ struct speedmap *smp = speedmap, *esmp = &speedmap[nspeeds];
+
+ while (smp < esmp) {
+ if (strcmp(str, smp->str) == 0)
+ return (smp->val);
+ smp++;
+ }
+ return B0;
+}
+
+int
+serialopen(char *device, speed_t speed)
+{
+ int fd;
+
+ if (cfsetospeed(&tios, speed) < 0)
+ return -1;
+
+ if ((fd = open(device, O_RDWR)) < 0)
+ return -1;
+
+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
+ (void)close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+int
+serialreadchar(int fd, int timeout)
+{
+ fd_set fds;
+ struct timeval tv;
+ int n;
+ char ch;
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ /* this is a fucking horrible quick hack - fix this */
+
+ if ((n = select(fd + 1, &fds, 0, 0, &tv)) < 0)
+ return SERIAL_ERROR;
+
+ if (n == 0)
+ return SERIAL_TIMEOUT;
+
+ if ((n = read(fd, &ch, 1)) < 0)
+ return SERIAL_ERROR;
+
+ if (n == 0)
+ return SERIAL_EOF;
+
+ return ch;
+}
+
+int
+serialwrite(int fd, char *buf, int len)
+{
+ int n;
+
+ do {
+ n = write(fd, buf, len);
+ if (n < 0)
+ return 1;
+ len -= n;
+ buf += n;
+ } while (len > 0);
+ return 0;
+}
+
+int
+serialclose(int fd)
+{
+ return close(fd);
+}
diff --git a/u-boot/tools/gdb/serial.h b/u-boot/tools/gdb/serial.h
new file mode 100644
index 0000000..3ed509e
--- /dev/null
+++ b/u-boot/tools/gdb/serial.h
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2000
+ * Murray Jensen <Murray.Jensen@csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * 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 <termios.h>
+
+#define SERIAL_ERROR -1 /* General error, see errno for details */
+#define SERIAL_TIMEOUT -2
+#define SERIAL_EOF -3
+
+extern speed_t cvtspeed(char *);
+extern int serialopen(char *, speed_t);
+extern int serialreadchar(int, int);
+extern int serialwrite(int, char *, int);
+extern int serialclose(int);