OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [gdb/] [dsrec.c] - Blame information for rev 1782

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.