* interp.c (sim_engine_run): msvc cpp barfs on #if (a==b!=c).
[deliverable/binutils-gdb.git] / gdb / dsrec.c
CommitLineData
56e327b3 1/* S-record download support for GDB, the GNU debugger.
8c3bd6a4 2 Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
56e327b3
FF
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "defs.h"
21#include "serial.h"
22#include "srec.h"
23#include <time.h>
24
8c3bd6a4 25int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
56e327b3
FF
26extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
27
28extern int remote_debug;
29
30static int make_srec PARAMS ((char *srec, CORE_ADDR targ_addr, bfd *abfd,
31 asection *sect, int sectoff, int *maxrecsize,
32 int flags));
33
8c3bd6a4
SS
34/* Download an executable by converting it to S records. DESC is a
35 serial_t to send the data to. FILE is the name of the file to be
36 loaded. LOAD_OFFSET is the offset into memory to load data into.
37 It is usually specified by the user and is useful with the a.out
38 file format. MAXRECSIZE is the length in chars of the largest
39 S-record the host can accomodate. This is measured from the
40 starting `S' to the last char of the checksum. FLAGS is various
41 random flags, and HASHMARK is non-zero to cause a `#' to be
42 printed out for each record loaded. WAITACK, if non-NULL, is a
43 function that waits for an acknowledgement after each S-record,
44 and returns non-zero if the ack is read correctly. */
56e327b3
FF
45
46void
47load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
48 serial_t desc;
49 const char *file;
50 bfd_vma load_offset;
51 int maxrecsize;
52 int flags;
53 int hashmark;
54 int (*waitack) PARAMS ((void));
55{
56 bfd *abfd;
57 asection *s;
58 char *srec;
59 int i;
60 int reclen;
61 time_t start_time, end_time;
62 unsigned long data_count = 0;
63
8c3bd6a4 64 srec = (char *) alloca (maxrecsize + 1);
56e327b3
FF
65
66 abfd = bfd_openr (file, 0);
67 if (!abfd)
68 {
69 printf_filtered ("Unable to open file %s\n", file);
70 return;
71 }
72
73 if (bfd_check_format (abfd, bfd_object) == 0)
74 {
75 printf_filtered ("File is not an object file\n");
76 return;
77 }
78
79 start_time = time (NULL);
8c3bd6a4
SS
80
81 /* Write a type 0 header record. no data for a type 0, and there
82 is no data, so len is 0. */
83
84 reclen = maxrecsize;
85 make_srec (srec, 0, NULL, NULL, 0, &reclen, flags);
86 if (remote_debug)
87 fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
88 SERIAL_WRITE (desc, srec, reclen);
89
56e327b3
FF
90 for (s = abfd->sections; s; s = s->next)
91 if (s->flags & SEC_LOAD)
92 {
93 int numbytes;
94 bfd_vma addr = bfd_get_section_vma (abfd, s) + load_offset;
95 bfd_size_type size = bfd_get_section_size_before_reloc (s);
8c3bd6a4 96 char * section_name = bfd_get_section_name (abfd, s);
56e327b3
FF
97
98 printf_filtered ("%s\t: 0x%08x .. 0x%08x ",
8c3bd6a4 99 section_name, (int) addr, (int) addr + size);
56e327b3
FF
100 gdb_flush (gdb_stdout);
101
102 data_count += size;
103
104 for (i = 0; i < size; i += numbytes)
105 {
106 reclen = maxrecsize;
107 numbytes = make_srec (srec, (CORE_ADDR) (addr + i), abfd, s,
108 i, &reclen, flags);
109
110 if (remote_debug)
111 fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
112
8c3bd6a4
SS
113 /* Repeatedly send the S-record until a good
114 acknowledgement is sent back. */
56e327b3
FF
115 do
116 {
117 SERIAL_WRITE (desc, srec, reclen);
8c3bd6a4
SS
118 if (ui_load_progress_hook)
119 if (ui_load_progress_hook (section_name, (unsigned long) i))
120 error ("Canceled the download");
56e327b3 121 }
8c3bd6a4 122 while (waitack != NULL && !waitack ());
56e327b3
FF
123
124 if (hashmark)
125 {
126 putchar_unfiltered ('#');
127 gdb_flush (gdb_stdout);
128 }
129 } /* Per-packet (or S-record) loop */
130
8c3bd6a4
SS
131 if (ui_load_progress_hook)
132 if (ui_load_progress_hook (section_name, (unsigned long) i))
133 error ("Canceled the download");
56e327b3 134 putchar_unfiltered ('\n');
8c3bd6a4 135 }
56e327b3
FF
136
137 if (hashmark)
138 putchar_unfiltered ('\n');
139
140 end_time = time (NULL);
141
8c3bd6a4 142 /* Write a terminator record. */
56e327b3
FF
143
144 reclen = maxrecsize;
145 make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
146
147 if (remote_debug)
148 fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
149 SERIAL_WRITE (desc, srec, reclen);
150
8c3bd6a4
SS
151 /* Some monitors need these to wake up properly. (Which ones? -sts) */
152 SERIAL_WRITE (desc, "\r\r", 2);
56e327b3
FF
153
154 SERIAL_FLUSH_INPUT (desc);
155
156 report_transfer_performance (data_count, start_time, end_time);
157}
158
159/*
160 * make_srec -- make an srecord. This writes each line, one at a
161 * time, each with it's own header and trailer line.
162 * An srecord looks like this:
163 *
164 * byte count-+ address
165 * start ---+ | | data +- checksum
166 * | | | |
167 * S01000006F6B692D746573742E73726563E4
168 * S315000448600000000000000000FC00005900000000E9
169 * S31A0004000023C1400037DE00F023604000377B009020825000348D
170 * S30B0004485A0000000000004E
171 * S70500040000F6
172 *
173 * S<type><length><address><data><checksum>
174 *
175 * Where
176 * - length
177 * is the number of bytes following upto the checksum. Note that
178 * this is not the number of chars following, since it takes two
179 * chars to represent a byte.
180 * - type
181 * is one of:
182 * 0) header record
183 * 1) two byte address data record
184 * 2) three byte address data record
185 * 3) four byte address data record
186 * 7) four byte address termination record
187 * 8) three byte address termination record
188 * 9) two byte address termination record
189 *
190 * - address
191 * is the start address of the data following, or in the case of
192 * a termination record, the start address of the image
193 * - data
194 * is the data.
195 * - checksum
196 * is the sum of all the raw byte data in the record, from the length
197 * upwards, modulo 256 and subtracted from 255.
198 *
199 * This routine returns the length of the S-record.
200 *
201 */
202
203static int
204make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
205 char *srec;
206 CORE_ADDR targ_addr;
207 bfd *abfd;
208 asection *sect;
209 int sectoff;
210 int *maxrecsize;
211 int flags;
212{
213 unsigned char checksum;
214 int tmp;
215 const static char hextab[] = "0123456789ABCDEF";
8c3bd6a4
SS
216 const static char data_code_table[] = "123";
217 const static char term_code_table[] = "987";
218 const static char *formats[] = { "S%c%02X%04X",
219 "S%c%02X%06X",
220 "S%c%02X%08X" };
56e327b3
FF
221 char const *code_table;
222 int addr_size;
223 int payload_size;
56e327b3
FF
224 char *binbuf;
225 char *p;
226
227 if (sect)
228 {
229 tmp = flags; /* Data record */
230 code_table = data_code_table;
231 binbuf = alloca (*maxrecsize/2);
232 }
233 else
234 {
235 tmp = flags >> SREC_TERM_SHIFT; /* Term record */
236 code_table = term_code_table;
237 }
238
239 if ((tmp & SREC_2_BYTE_ADDR) && (targ_addr <= 0xffff))
240 addr_size = 2;
241 else if ((tmp & SREC_3_BYTE_ADDR) && (targ_addr <= 0xffffff))
242 addr_size = 3;
243 else if (tmp & SREC_4_BYTE_ADDR)
244 addr_size = 4;
245 else
8c3bd6a4
SS
246 fatal ("make_srec: Bad address (0x%x), or bad flags (0x%x).",
247 targ_addr, flags);
56e327b3 248
8c3bd6a4
SS
249 /* Now that we know the address size, we can figure out how much
250 data this record can hold. */
56e327b3
FF
251
252 if (sect)
253 {
254 payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
255 payload_size = min (payload_size, sect->_raw_size - sectoff);
256
257 bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
258 }
259 else
260 payload_size = 0; /* Term packets have no payload */
261
8c3bd6a4 262 /* Output the header. */
56e327b3 263
8c3bd6a4 264 sprintf (srec, formats[addr_size - 2], code_table[addr_size - 2],
56e327b3
FF
265 addr_size + payload_size + 1, targ_addr);
266
8c3bd6a4
SS
267 /* Note that the checksum is calculated on the raw data, not the
268 hexified data. It includes the length, address and the data
269 portions of the packet. */
56e327b3
FF
270
271 checksum = 0;
272
8c3bd6a4
SS
273 checksum += (payload_size + addr_size + 1 /* Packet length */
274 + (targ_addr & 0xff) /* Address... */
56e327b3
FF
275 + ((targ_addr >> 8) & 0xff)
276 + ((targ_addr >> 16) & 0xff)
277 + ((targ_addr >> 24) & 0xff));
278
279 p = srec + 1 + 1 + 2 + addr_size * 2;
280
8c3bd6a4 281 /* Build the Srecord. */
56e327b3
FF
282 for (tmp = 0; tmp < payload_size; tmp++)
283 {
284 unsigned char k;
285
286 k = binbuf[tmp];
287 *p++ = hextab [k >> 4];
288 *p++ = hextab [k & 0xf];
289 checksum += k;
290 }
291
292 checksum = ~checksum;
293
294 *p++ = hextab[checksum >> 4];
295 *p++ = hextab[checksum & 0xf];
296 *p++ = '\r';
297
298 *maxrecsize = p - srec;
299 return payload_size;
300}
This page took 0.069179 seconds and 4 git commands to generate.