]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/xmodem.c
import gdb-1999-07-07 post reformat
[thirdparty/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 (desc, timeout)
40 serial_t desc;
41 int timeout;
42 {
43 int c;
44
45 c = SERIAL_READCHAR (desc, timeout);
46
47 if (remote_debug > 0)
48 fputc_unfiltered (c, gdb_stdlog);
49
50 if (c >= 0)
51 return c;
52
53 if (c == SERIAL_TIMEOUT)
54 error ("Timeout reading from remote system.");
55
56 perror_with_name ("xmodem.c:readchar()");
57 }
58
59 #define CRC16 0x1021 /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
60
61 static unsigned short *crctab;
62
63 /* Call this to init the fast CRC-16 calculation table. */
64
65 static void
66 crcinit ()
67 {
68 static int crctab_inited = 0;
69 int val;
70
71 if (crctab_inited == 1)
72 return;
73
74 crctab = xmalloc (256 * sizeof (short));
75
76 for (val = 0; val <= 255; val++)
77 {
78 int i;
79 unsigned int crc;
80
81 crc = val << 8;
82
83 for (i = 0; i < 8; ++i)
84 {
85 crc <<= 1;
86
87 if (crc & 0x10000)
88 crc ^= CRC16;
89 }
90
91 crctab[val] = crc;
92 }
93
94 crctab_inited = 1;
95 }
96
97 /* Calculate a CRC-16 for the LEN byte message pointed at by P. */
98
99 static unsigned short
100 docrc (p, len)
101 unsigned char *p;
102 int len;
103 {
104 unsigned short crc = 0;
105
106 while (len-- > 0)
107 crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];
108
109 return crc;
110 }
111
112 /* Start up the transmit process. Reset state variables. Wait for receiver to
113 send NAK or CRC request. */
114
115 int
116 xmodem_init_xfer (desc)
117 serial_t desc;
118 {
119 int c;
120 int i;
121
122 blknum = 1;
123 crcflag = 0;
124 crcinit ();
125
126 for (i = 1; i <= 10; i++)
127 {
128 c = readchar (desc, 6);
129
130 switch (c)
131 {
132 case 'C':
133 crcflag = 1;
134 case NAK:
135 return 0;
136 default:
137 fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
138 continue;
139 case CANCEL: /* target aborted load */
140 fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
141 continue;
142 }
143 }
144 error ("xmodem_init_xfer: Too many unexpected characters.");
145 }
146
147 /* Take 128 bytes of data and make a packet out of it.
148
149 * Each packet looks like this:
150 * +-----+-------+-------+------+-----+
151 * | SOH | Seq1. | Seq2. | data | SUM |
152 * +-----+-------+-------+------+-----+
153 * SOH = 0x01
154 * Seq1 = The sequence number.
155 * Seq2 = The complement of the sequence number.
156 * Data = A 128 bytes of data.
157 * SUM = Add the contents of the 128 bytes and use the low-order
158 * 8 bits of the result.
159 *
160 * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
161 * remote system. PACKET must be XMODEM_PACKETSIZE bytes long. The data must
162 * start 3 bytes after the beginning of the packet to leave room for the
163 * XMODEM header. LEN is the length of the data portion of the packet (and
164 * must be <= 128 bytes). If it is < 128 bytes, ^Z padding will be added.
165 */
166
167 void
168 xmodem_send_packet (desc, packet, len, hashmark)
169 serial_t desc;
170 unsigned char *packet;
171 int len;
172 int hashmark;
173 {
174 int i;
175 int retries;
176 int pktlen;
177 int datasize;
178
179 /* build the packet header */
180
181 packet[1] = blknum;
182 packet[2] = ~blknum;
183
184 blknum++;
185
186 if (len <= XMODEM_DATASIZE)
187 {
188 packet[0] = SOH;
189 datasize = XMODEM_DATASIZE;
190 }
191 else if (len <= XMODEM_1KDATASIZE)
192 {
193 packet[0] = STX;
194 datasize = XMODEM_1KDATASIZE;
195 }
196 else
197 abort (); /* Packet way too large */
198
199 /* Add ^Z padding if packet < 128 (or 1024) bytes */
200
201 memset (packet + 3 + len, '\026', datasize - len);
202
203 if (crcflag)
204 {
205 int crc;
206
207 crc = docrc (packet + 3, datasize);
208
209 packet[3 + datasize] = crc >> 8;
210 packet[3 + datasize + 1] = crc;
211 pktlen = datasize + 5;
212 }
213 else
214 {
215 int sum;
216
217 sum = 0;
218 for (i = 3; i < datasize + 3; i++)
219 sum += packet[i];
220
221 packet[3 + datasize] = sum; /* add the checksum */
222 pktlen = datasize + 4;
223 }
224
225 for (retries = 3; retries >= 0; retries--)
226 {
227 int c;
228
229 SERIAL_WRITE (desc, packet, pktlen);
230
231 c = readchar (desc, 3);
232 switch (c)
233 {
234 case ACK:
235 return;
236 case NAK:
237 if (!hashmark)
238 continue;
239 putchar_unfiltered ('-');
240 gdb_flush (gdb_stdout);
241 continue;
242 case CANCEL:
243 error ("xmodem_send_packet: Transfer aborted by receiver.");
244 default:
245 fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
246 continue;
247 }
248 }
249
250 SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
251
252 error ("xmodem_send_packet: Excessive retries.");
253 }
254
255 /* Finish off the transfer. Send out the EOT, and wait for an ACK. */
256
257 void
258 xmodem_finish_xfer (desc)
259 serial_t desc;
260 {
261 int retries;
262
263 for (retries = 10; retries >= 0; retries--)
264 {
265 int c;
266
267 SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
268
269 c = readchar (desc, 3);
270 switch (c)
271 {
272 case ACK:
273 return;
274 case NAK:
275 continue;
276 case CANCEL:
277 error ("xmodem_finish_xfer: Transfer aborted by receiver.");
278 default:
279 fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
280 continue;
281 }
282 }
283
284 error ("xmodem_finish_xfer: Excessive retries.");
285 }