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