diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-11-23 04:12:06 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-11-23 04:12:06 +0000 |
commit | 37d4621bd4a912b6a032bc21906f7032e602cbf2 (patch) | |
tree | 6e6f3dad18baebc5f90abdcbbf4a8ba242555627 /gnu/usr.bin/binutils/gdb/xmodem.c | |
parent | fb7c7a778840ea235dd0bb550cfd2e2ac8ccb37c (diff) |
Merge to Cygnus 961112 + add some support (not ready) for shared libs
Diffstat (limited to 'gnu/usr.bin/binutils/gdb/xmodem.c')
-rw-r--r-- | gnu/usr.bin/binutils/gdb/xmodem.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/gdb/xmodem.c b/gnu/usr.bin/binutils/gdb/xmodem.c new file mode 100644 index 00000000000..dd13b873c14 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/xmodem.c @@ -0,0 +1,284 @@ +/* XMODEM support for GDB, the GNU debugger. + Copyright 1995 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. */ + +#include "defs.h" +#include "serial.h" +#include "target.h" +#include "xmodem.h" + +/* These definitions are for xmodem protocol. */ + +#define SOH 0x01 +#define STX 0x02 +#define ACK 0x06 +#define NAK 0x15 +#define EOT 0x04 +#define CANCEL 0x18 + +static int blknum; /* XMODEM block number */ +static int crcflag; /* Sez we are using CRC's instead of cksums */ + +static int +readchar (desc, timeout) + serial_t desc; + int timeout; +{ + int c; + + c = SERIAL_READCHAR (desc, timeout); + + if (remote_debug > 0) + fputc_unfiltered (c, gdb_stderr); + + if (c >= 0) + return c; + + if (c == SERIAL_TIMEOUT) + error ("Timeout reading from remote system."); + + perror_with_name ("xmodem.c:readchar()"); +} + +#define CRC16 0x1021 /* Generator polynomial (X^16 + X^12 + X^5 + 1) */ + +static unsigned short *crctab; + +/* Call this to init the fast CRC-16 calculation table. */ + +static void +crcinit () +{ + static int crctab_inited = 0; + int val; + + if (crctab_inited == 1) + return; + + crctab = xmalloc (256 * sizeof (short)); + + for (val = 0; val <= 255; val++) + { + int i; + unsigned int crc; + + crc = val << 8; + + for (i = 0; i < 8; ++i) + { + crc <<= 1; + + if (crc & 0x10000) + crc ^= CRC16; + } + + crctab [val] = crc; + } + + crctab_inited = 1; +} + +/* Calculate a CRC-16 for the LEN byte message pointed at by P. */ + +static unsigned short +docrc (p, len) + unsigned char *p; + int len; +{ + unsigned short crc = 0; + + while (len-- > 0) + crc = (crc << 8) ^ crctab [(crc >> 8) ^ *p++]; + + return crc; +} + +/* Start up the transmit process. Reset state variables. Wait for receiver to + send NAK or CRC request. */ + +int +xmodem_init_xfer (desc) + serial_t desc; +{ + int c; + int i; + + blknum = 1; + crcflag = 0; + crcinit (); + + for (i = 1; i <= 10; i++) + { + c = readchar (desc, 6); + + switch (c) + { + case 'C': + crcflag = 1; + case NAK: + return 0; + default: + fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c); + continue; + case CANCEL: /* target aborted load */ + fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n"); + continue; + } + } + error ("xmodem_init_xfer: Too many unexpected characters."); +} + +/* Take 128 bytes of data and make a packet out of it. + * + * Each packet looks like this: + * +-----+-------+-------+------+-----+ + * | SOH | Seq1. | Seq2. | data | SUM | + * +-----+-------+-------+------+-----+ + * SOH = 0x01 + * Seq1 = The sequence number. + * Seq2 = The complement of the sequence number. + * Data = A 128 bytes of data. + * SUM = Add the contents of the 128 bytes and use the low-order + * 8 bits of the result. + * + * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the + * remote system. PACKET must be XMODEM_PACKETSIZE bytes long. The data must + * start 3 bytes after the beginning of the packet to leave room for the + * XMODEM header. LEN is the length of the data portion of the packet (and + * must be <= 128 bytes). If it is < 128 bytes, ^Z padding will be added. + */ + +void +xmodem_send_packet (desc, packet, len, hashmark) + serial_t desc; + unsigned char *packet; + int len; + int hashmark; +{ + int i; + int retries; + int pktlen; + int datasize; + + /* build the packet header */ + + packet[1] = blknum; + packet[2] = ~blknum; + + blknum++; + + if (len <= XMODEM_DATASIZE) + { + packet[0] = SOH; + datasize = XMODEM_DATASIZE; + } + else if (len <= XMODEM_1KDATASIZE) + { + packet[0] = STX; + datasize = XMODEM_1KDATASIZE; + } + else + abort (); /* Packet way too large */ + + /* Add ^Z padding if packet < 128 (or 1024) bytes */ + + memset (packet + 3 + len, '\026', datasize - len); + + if (crcflag) + { + int crc; + + crc = docrc (packet + 3, datasize); + + packet[3 + datasize] = crc >> 8; + packet[3 + datasize + 1] = crc; + pktlen = datasize + 5; + } + else + { + int sum; + + sum = 0; + for (i = 3; i < datasize + 3; i++) + sum += packet[i]; + + packet[3 + datasize] = sum; /* add the checksum */ + pktlen = datasize + 4; + } + + for (retries = 3; retries >= 0; retries--) + { + int c; + + SERIAL_WRITE (desc, packet, pktlen); + + c = readchar (desc, 3); + switch (c) + { + case ACK: + return; + case NAK: + if (!hashmark) + continue; + putchar_unfiltered ('-'); + gdb_flush (gdb_stdout); + continue; + case CANCEL: + error ("xmodem_send_packet: Transfer aborted by receiver."); + default: + fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c); + continue; + } + } + + SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */ + + error ("xmodem_send_packet: Excessive retries."); +} + +/* Finish off the transfer. Send out the EOT, and wait for an ACK. */ + +void +xmodem_finish_xfer (desc) + serial_t desc; +{ + int retries; + + for (retries = 10; retries >= 0; retries--) + { + int c; + + SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */ + + c = readchar (desc, 3); + switch (c) + { + case ACK: + return; + case NAK: + continue; + case CANCEL: + error ("xmodem_finish_xfer: Transfer aborted by receiver."); + default: + fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c); + continue; + } + } + + error ("xmodem_finish_xfer: Excessive retries."); +} |