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