Replace calls to abort() with calls to internal_error().
[deliverable/binutils-gdb.git] / gdb / xmodem.c
1 /* XMODEM support for GDB, the GNU debugger.
2 Copyright 1995 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include "defs.h"
22 #include "serial.h"
23 #include "target.h"
24 #include "xmodem.h"
25
26 /* These definitions are for xmodem protocol. */
27
28 #define SOH 0x01
29 #define STX 0x02
30 #define ACK 0x06
31 #define NAK 0x15
32 #define EOT 0x04
33 #define CANCEL 0x18
34
35 static int blknum; /* XMODEM block number */
36 static int crcflag; /* Sez we are using CRC's instead of cksums */
37
38 static int
39 readchar (serial_t desc, int timeout)
40 {
41 int c;
42
43 c = SERIAL_READCHAR (desc, timeout);
44
45 if (remote_debug > 0)
46 fputc_unfiltered (c, gdb_stdlog);
47
48 if (c >= 0)
49 return c;
50
51 if (c == SERIAL_TIMEOUT)
52 error ("Timeout reading from remote system.");
53
54 perror_with_name ("xmodem.c:readchar()");
55 }
56
57 #define CRC16 0x1021 /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
58
59 static unsigned short *crctab;
60
61 /* Call this to init the fast CRC-16 calculation table. */
62
63 static void
64 crcinit (void)
65 {
66 static int crctab_inited = 0;
67 int val;
68
69 if (crctab_inited == 1)
70 return;
71
72 crctab = xmalloc (256 * sizeof (short));
73
74 for (val = 0; val <= 255; val++)
75 {
76 int i;
77 unsigned int crc;
78
79 crc = val << 8;
80
81 for (i = 0; i < 8; ++i)
82 {
83 crc <<= 1;
84
85 if (crc & 0x10000)
86 crc ^= CRC16;
87 }
88
89 crctab[val] = crc;
90 }
91
92 crctab_inited = 1;
93 }
94
95 /* Calculate a CRC-16 for the LEN byte message pointed at by P. */
96
97 static unsigned short
98 docrc (unsigned char *p, int len)
99 {
100 unsigned short crc = 0;
101
102 while (len-- > 0)
103 crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];
104
105 return crc;
106 }
107
108 /* Start up the transmit process. Reset state variables. Wait for receiver to
109 send NAK or CRC request. */
110
111 int
112 xmodem_init_xfer (serial_t desc)
113 {
114 int c;
115 int i;
116
117 blknum = 1;
118 crcflag = 0;
119 crcinit ();
120
121 for (i = 1; i <= 10; i++)
122 {
123 c = readchar (desc, 6);
124
125 switch (c)
126 {
127 case 'C':
128 crcflag = 1;
129 case NAK:
130 return 0;
131 default:
132 fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
133 continue;
134 case CANCEL: /* target aborted load */
135 fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
136 continue;
137 }
138 }
139 error ("xmodem_init_xfer: Too many unexpected characters.");
140 }
141
142 /* Take 128 bytes of data and make a packet out of it.
143
144 * Each packet looks like this:
145 * +-----+-------+-------+------+-----+
146 * | SOH | Seq1. | Seq2. | data | SUM |
147 * +-----+-------+-------+------+-----+
148 * SOH = 0x01
149 * Seq1 = The sequence number.
150 * Seq2 = The complement of the sequence number.
151 * Data = A 128 bytes of data.
152 * SUM = Add the contents of the 128 bytes and use the low-order
153 * 8 bits of the result.
154 *
155 * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
156 * remote system. PACKET must be XMODEM_PACKETSIZE bytes long. The data must
157 * start 3 bytes after the beginning of the packet to leave room for the
158 * XMODEM header. LEN is the length of the data portion of the packet (and
159 * must be <= 128 bytes). If it is < 128 bytes, ^Z padding will be added.
160 */
161
162 void
163 xmodem_send_packet (serial_t desc, unsigned char *packet, int len, int hashmark)
164 {
165 int i;
166 int retries;
167 int pktlen;
168 int datasize;
169
170 /* build the packet header */
171
172 packet[1] = blknum;
173 packet[2] = ~blknum;
174
175 blknum++;
176
177 if (len <= XMODEM_DATASIZE)
178 {
179 packet[0] = SOH;
180 datasize = XMODEM_DATASIZE;
181 }
182 else if (len <= XMODEM_1KDATASIZE)
183 {
184 packet[0] = STX;
185 datasize = XMODEM_1KDATASIZE;
186 }
187 else
188 internal_error (__FILE__, __LINE__, "failed internal consistency check"); /* Packet way too large */
189
190 /* Add ^Z padding if packet < 128 (or 1024) bytes */
191
192 memset (packet + 3 + len, '\026', datasize - len);
193
194 if (crcflag)
195 {
196 int crc;
197
198 crc = docrc (packet + 3, datasize);
199
200 packet[3 + datasize] = crc >> 8;
201 packet[3 + datasize + 1] = crc;
202 pktlen = datasize + 5;
203 }
204 else
205 {
206 int sum;
207
208 sum = 0;
209 for (i = 3; i < datasize + 3; i++)
210 sum += packet[i];
211
212 packet[3 + datasize] = sum; /* add the checksum */
213 pktlen = datasize + 4;
214 }
215
216 for (retries = 3; retries >= 0; retries--)
217 {
218 int c;
219
220 SERIAL_WRITE (desc, packet, pktlen);
221
222 c = readchar (desc, 3);
223 switch (c)
224 {
225 case ACK:
226 return;
227 case NAK:
228 if (!hashmark)
229 continue;
230 putchar_unfiltered ('-');
231 gdb_flush (gdb_stdout);
232 continue;
233 case CANCEL:
234 error ("xmodem_send_packet: Transfer aborted by receiver.");
235 default:
236 fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
237 continue;
238 }
239 }
240
241 SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
242
243 error ("xmodem_send_packet: Excessive retries.");
244 }
245
246 /* Finish off the transfer. Send out the EOT, and wait for an ACK. */
247
248 void
249 xmodem_finish_xfer (serial_t desc)
250 {
251 int retries;
252
253 for (retries = 10; retries >= 0; retries--)
254 {
255 int c;
256
257 SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
258
259 c = readchar (desc, 3);
260 switch (c)
261 {
262 case ACK:
263 return;
264 case NAK:
265 continue;
266 case CANCEL:
267 error ("xmodem_finish_xfer: Transfer aborted by receiver.");
268 default:
269 fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
270 continue;
271 }
272 }
273
274 error ("xmodem_finish_xfer: Excessive retries.");
275 }
This page took 0.041211 seconds and 4 git commands to generate.