xref: /openbsd-src/gnu/usr.bin/binutils/gdb/dsrec.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* S-record download support for GDB, the GNU debugger.
2    Copyright 1995, 1996 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 "srec.h"
23 
24 extern int remote_debug;
25 
26 static int make_srec PARAMS ((char *srec, CORE_ADDR targ_addr, bfd *abfd,
27 			      asection *sect, int sectoff, int *maxrecsize,
28 			      int flags));
29 
30 /*  Download an executable by converting it to S records.  DESC is a serial_t
31     to send the data to.  FILE is the name of the file to be loaded.
32     MAXRECSIZE is the length in chars of the largest S-record the host can
33     accomodate.  This is measured from the starting `S' to the last char of the
34     checksum.  FLAGS is various random flags, and HASHMARK is non-zero to cause
35     a `#' to be printed out for each record loaded.  WAITACK, if non-NULL, is
36     a function that waits for an acknowledgement after each S-record, and
37     returns non-zero if the ack is read correctly.  */
38 
39 void
40 load_srec (desc, file, maxrecsize, flags, hashmark, waitack)
41      serial_t desc;
42      const char *file;
43      int maxrecsize;
44      int flags;
45      int hashmark;
46      int (*waitack) PARAMS ((void));
47 {
48   bfd *abfd;
49   asection *s;
50   char *srec;
51   int i;
52   int reclen;
53 
54   srec = (char *)alloca (maxrecsize + 1);
55 
56   abfd = bfd_openr (file, 0);
57   if (!abfd)
58     {
59       printf_filtered ("Unable to open file %s\n", file);
60       return;
61     }
62 
63   if (bfd_check_format (abfd, bfd_object) == 0)
64     {
65       printf_filtered ("File is not an object file\n");
66       return;
67     }
68 
69   for (s = abfd->sections; s; s = s->next)
70     if (s->flags & SEC_LOAD)
71       {
72 	int numbytes;
73 
74 	printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
75 			 s->vma + s->_raw_size);
76 	gdb_flush (gdb_stdout);
77 
78 	for (i = 0; i < s->_raw_size; i += numbytes)
79 	  {
80 	    reclen = maxrecsize;
81 	    numbytes = make_srec (srec, s->vma + i, abfd, s, i, &reclen,
82 				  flags);
83 
84 	    if (remote_debug)
85 	      fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
86 
87 	    /* Repeatedly send the S-record until a good acknowledgement
88 	       is sent back.  */
89 	    do
90 	      {
91 	        SERIAL_WRITE (desc, srec, reclen);
92 	      }
93 	    while (waitack != NULL && !waitack());
94 
95 	    if (hashmark)
96 	      {
97 		putchar_unfiltered ('#');
98 		gdb_flush (gdb_stdout);
99 	      }
100 	  }			/* Per-packet (or S-record) loop */
101 
102 	putchar_unfiltered ('\n');
103       }				/* Loadable sections */
104 
105   if (hashmark)
106     putchar_unfiltered ('\n');
107 
108   /* Write a type 7 terminator record. no data for a type 7, and there
109      is no data, so len is 0.  */
110 
111   reclen = maxrecsize;
112   make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
113 
114   if (remote_debug)
115     fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
116   SERIAL_WRITE (desc, srec, reclen);
117 
118   SERIAL_WRITE (desc, "\r\r", 2); /* Some monitors need these to wake up */
119 
120   SERIAL_FLUSH_INPUT (desc);
121 }
122 
123 /*
124  * make_srec -- make an srecord. This writes each line, one at a
125  *	time, each with it's own header and trailer line.
126  *	An srecord looks like this:
127  *
128  * byte count-+     address
129  * start ---+ |        |       data        +- checksum
130  *	    | |        |                   |
131  *	  S01000006F6B692D746573742E73726563E4
132  *	  S315000448600000000000000000FC00005900000000E9
133  *	  S31A0004000023C1400037DE00F023604000377B009020825000348D
134  *	  S30B0004485A0000000000004E
135  *	  S70500040000F6
136  *
137  *	S<type><length><address><data><checksum>
138  *
139  *      Where
140  *      - length
141  *        is the number of bytes following upto the checksum. Note that
142  *        this is not the number of chars following, since it takes two
143  *        chars to represent a byte.
144  *      - type
145  *        is one of:
146  *        0) header record
147  *        1) two byte address data record
148  *        2) three byte address data record
149  *        3) four byte address data record
150  *        7) four byte address termination record
151  *        8) three byte address termination record
152  *        9) two byte address termination record
153  *
154  *      - address
155  *        is the start address of the data following, or in the case of
156  *        a termination record, the start address of the image
157  *      - data
158  *        is the data.
159  *      - checksum
160  *	  is the sum of all the raw byte data in the record, from the length
161  *        upwards, modulo 256 and subtracted from 255.
162  *
163  * This routine returns the length of the S-record.
164  *
165  */
166 
167 static int
168 make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
169      char *srec;
170      CORE_ADDR targ_addr;
171      bfd *abfd;
172      asection *sect;
173      int sectoff;
174      int *maxrecsize;
175      int flags;
176 {
177   unsigned char checksum;
178   int tmp;
179   const static char hextab[] = "0123456789ABCDEF";
180   const static char data_code_table[] = "xx123";
181   const static char term_code_table[] = "xx987";
182   const static char *formats[] = {NULL, NULL, "S%c%02X%04X", "S%c%02X%06X",
183 				    "S%c%02X%08X"};
184   char const *code_table;
185   int addr_size;
186   int payload_size;
187   int type_code;
188   char *binbuf;
189   char *p;
190 
191   if (sect)
192     {
193       tmp = flags;		/* Data record */
194       code_table = data_code_table;
195       binbuf = alloca (*maxrecsize/2);
196     }
197   else
198     {
199       tmp = flags >> SREC_TERM_SHIFT; /* Term record */
200       code_table = term_code_table;
201     }
202 
203   if ((tmp & SREC_2_BYTE_ADDR) && (targ_addr <= 0xffff))
204     addr_size = 2;
205   else if ((tmp & SREC_3_BYTE_ADDR) && (targ_addr <= 0xffffff))
206     addr_size = 3;
207   else if (tmp & SREC_4_BYTE_ADDR)
208     addr_size = 4;
209   else
210     fatal ("make_srec:  Bad address (0x%x), or bad flags (0x%x).", targ_addr,
211 	   flags);
212 
213 /* Now that we know the address size, we can figure out how much data this
214    record can hold.  */
215 
216   if (sect)
217     {
218       payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
219       payload_size = min (payload_size, sect->_raw_size - sectoff);
220 
221       bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
222     }
223   else
224     payload_size = 0;		/* Term packets have no payload */
225 
226 /* Output the header.  */
227 
228   sprintf (srec, formats[addr_size], code_table[addr_size],
229 	   addr_size + payload_size + 1, targ_addr);
230 
231 /* Note that the checksum is calculated on the raw data, not the hexified
232    data.  It includes the length, address and the data portions of the
233    packet.  */
234 
235   checksum = 0;
236 
237   checksum += (payload_size + addr_size + 1 /* Packet length */
238 	       + (targ_addr & 0xff)	/* Address... */
239 	       + ((targ_addr >>  8) & 0xff)
240 	       + ((targ_addr >> 16) & 0xff)
241 	       + ((targ_addr >> 24) & 0xff));
242 
243   p = srec + 1 + 1 + 2 + addr_size * 2;
244 
245   /* build the srecord */
246   for (tmp = 0; tmp < payload_size; tmp++)
247     {
248       unsigned char k;
249 
250       k = binbuf[tmp];
251       *p++ = hextab [k >> 4];
252       *p++ = hextab [k & 0xf];
253       checksum += k;
254     }
255 
256   checksum = ~checksum;
257 
258   *p++ = hextab[checksum >> 4];
259   *p++ = hextab[checksum & 0xf];
260   *p++ = '\r';
261 
262   *maxrecsize = p - srec;
263   return payload_size;
264 }
265