1 /*
2 * avrdude - A Downloader/Uploader for AVR device programmers
3 * Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /* $Id: fileio.c 1338 2014-10-15 20:01:12Z joerg_wunsch $ */
20
21 #include "ac_cfg.h"
22
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <stdint.h>
30
31 #ifdef HAVE_LIBELF
32 #ifdef HAVE_LIBELF_H
33 #include <libelf.h>
34 #elif defined(HAVE_LIBELF_LIBELF_H)
35 #include <libelf/libelf.h>
36 #endif
37 #define EM_AVR32 0x18ad /* inofficial */
38 #endif
39
40 #include "avrdude.h"
41 #include "libavrdude.h"
42
43
44 #define IHEX_MAXDATA 256
45
46 #define MAX_LINE_LEN 256 /* max line length for ASCII format input files */
47
48
49 struct ihexrec {
50 unsigned char reclen;
51 unsigned int loadofs;
52 unsigned char rectyp;
53 unsigned char data[IHEX_MAXDATA];
54 unsigned char cksum;
55 };
56
57
58 static int b2ihex(unsigned char * inbuf, int bufsize,
59 int recsize, int startaddr,
60 char * outfile, FILE * outf);
61
62 static int ihex2b(char * infile, FILE * inf,
63 AVRMEM * mem, int bufsize, unsigned int fileoffset);
64
65 static int b2srec(unsigned char * inbuf, int bufsize,
66 int recsize, int startaddr,
67 char * outfile, FILE * outf);
68
69 static int srec2b(char * infile, FILE * inf,
70 AVRMEM * mem, int bufsize, unsigned int fileoffset);
71
72 static int ihex_readrec(struct ihexrec * ihex, char * rec);
73
74 static int srec_readrec(struct ihexrec * srec, char * rec);
75
76 static int fileio_rbin(struct fioparms * fio,
77 char * filename, FILE * f, AVRMEM * mem, int size);
78
79 static int fileio_ihex(struct fioparms * fio,
80 char * filename, FILE * f, AVRMEM * mem, int size);
81
82 static int fileio_srec(struct fioparms * fio,
83 char * filename, FILE * f, AVRMEM * mem, int size);
84
85 #ifdef HAVE_LIBELF
86 static int elf2b(char * infile, FILE * inf,
87 AVRMEM * mem, struct avrpart * p,
88 int bufsize, unsigned int fileoffset);
89
90 static int fileio_elf(struct fioparms * fio,
91 char * filename, FILE * f, AVRMEM * mem,
92 struct avrpart * p, int size);
93 #endif
94
95 static int fileio_num(struct fioparms * fio,
96 char * filename, FILE * f, AVRMEM * mem, int size,
97 FILEFMT fmt);
98
99 static int fmt_autodetect(char * fname);
100
101
102
fmtstr(FILEFMT format)103 char * fmtstr(FILEFMT format)
104 {
105 switch (format) {
106 case FMT_AUTO : return "auto-detect"; break;
107 case FMT_SREC : return "Motorola S-Record"; break;
108 case FMT_IHEX : return "Intel Hex"; break;
109 case FMT_RBIN : return "raw binary"; break;
110 case FMT_ELF : return "ELF"; break;
111 default : return "invalid format"; break;
112 };
113 }
114
115
116
b2ihex(unsigned char * inbuf,int bufsize,int recsize,int startaddr,char * outfile,FILE * outf)117 static int b2ihex(unsigned char * inbuf, int bufsize,
118 int recsize, int startaddr,
119 char * outfile, FILE * outf)
120 {
121 unsigned char * buf;
122 unsigned int nextaddr;
123 int n, nbytes, n_64k;
124 int i;
125 unsigned char cksum;
126
127 if (recsize > 255) {
128 avrdude_message(MSG_INFO, "%s: recsize=%d, must be < 256\n",
129 progname, recsize);
130 return -1;
131 }
132
133 n_64k = 0;
134 nextaddr = startaddr;
135 buf = inbuf;
136 nbytes = 0;
137
138 while (bufsize) {
139 n = recsize;
140 if (n > bufsize)
141 n = bufsize;
142
143 if ((nextaddr + n) > 0x10000)
144 n = 0x10000 - nextaddr;
145
146 if (n) {
147 cksum = 0;
148 fprintf(outf, ":%02X%04X00", n, nextaddr);
149 cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff);
150 for (i=0; i<n; i++) {
151 fprintf(outf, "%02X", buf[i]);
152 cksum += buf[i];
153 }
154 cksum = -cksum;
155 fprintf(outf, "%02X\n", cksum);
156
157 nextaddr += n;
158 nbytes += n;
159 }
160
161 if (nextaddr >= 0x10000) {
162 int lo, hi;
163 /* output an extended address record */
164 n_64k++;
165 lo = n_64k & 0xff;
166 hi = (n_64k >> 8) & 0xff;
167 cksum = 0;
168 fprintf(outf, ":02000004%02X%02X", hi, lo);
169 cksum += 2 + 0 + 4 + hi + lo;
170 cksum = -cksum;
171 fprintf(outf, "%02X\n", cksum);
172 nextaddr = 0;
173 }
174
175 /* advance to next 'recsize' bytes */
176 buf += n;
177 bufsize -= n;
178 }
179
180 /*-----------------------------------------------------------------
181 add the end of record data line
182 -----------------------------------------------------------------*/
183 cksum = 0;
184 n = 0;
185 nextaddr = 0;
186 fprintf(outf, ":%02X%04X01", n, nextaddr);
187 cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff) + 1;
188 cksum = -cksum;
189 fprintf(outf, "%02X\n", cksum);
190
191 return nbytes;
192 }
193
194
ihex_readrec(struct ihexrec * ihex,char * rec)195 static int ihex_readrec(struct ihexrec * ihex, char * rec)
196 {
197 int i, j;
198 char buf[8];
199 int offset, len;
200 char * e;
201 unsigned char cksum;
202 int rc;
203
204 len = strlen(rec);
205 offset = 1;
206 cksum = 0;
207
208 /* reclen */
209 if (offset + 2 > len)
210 return -1;
211 for (i=0; i<2; i++)
212 buf[i] = rec[offset++];
213 buf[i] = 0;
214 ihex->reclen = strtoul(buf, &e, 16);
215 if (e == buf || *e != 0)
216 return -1;
217
218 /* load offset */
219 if (offset + 4 > len)
220 return -1;
221 for (i=0; i<4; i++)
222 buf[i] = rec[offset++];
223 buf[i] = 0;
224 ihex->loadofs = strtoul(buf, &e, 16);
225 if (e == buf || *e != 0)
226 return -1;
227
228 /* record type */
229 if (offset + 2 > len)
230 return -1;
231 for (i=0; i<2; i++)
232 buf[i] = rec[offset++];
233 buf[i] = 0;
234 ihex->rectyp = strtoul(buf, &e, 16);
235 if (e == buf || *e != 0)
236 return -1;
237
238 cksum = ihex->reclen + ((ihex->loadofs >> 8) & 0x0ff) +
239 (ihex->loadofs & 0x0ff) + ihex->rectyp;
240
241 /* data */
242 for (j=0; j<ihex->reclen; j++) {
243 if (offset + 2 > len)
244 return -1;
245 for (i=0; i<2; i++)
246 buf[i] = rec[offset++];
247 buf[i] = 0;
248 ihex->data[j] = strtoul(buf, &e, 16);
249 if (e == buf || *e != 0)
250 return -1;
251 cksum += ihex->data[j];
252 }
253
254 /* cksum */
255 if (offset + 2 > len)
256 return -1;
257 for (i=0; i<2; i++)
258 buf[i] = rec[offset++];
259 buf[i] = 0;
260 ihex->cksum = strtoul(buf, &e, 16);
261 if (e == buf || *e != 0)
262 return -1;
263
264 rc = -cksum & 0x000000ff;
265
266 return rc;
267 }
268
269
270
271 /*
272 * Intel Hex to binary buffer
273 *
274 * Given an open file 'inf' which contains Intel Hex formated data,
275 * parse the file and lay it out within the memory buffer pointed to
276 * by outbuf. The size of outbuf, 'bufsize' is honored; if data would
277 * fall outsize of the memory buffer outbuf, an error is generated.
278 *
279 * Return the maximum memory address within 'outbuf' that was written.
280 * If an error occurs, return -1.
281 *
282 * */
ihex2b(char * infile,FILE * inf,AVRMEM * mem,int bufsize,unsigned int fileoffset)283 static int ihex2b(char * infile, FILE * inf,
284 AVRMEM * mem, int bufsize, unsigned int fileoffset)
285 {
286 char buffer [ MAX_LINE_LEN ];
287 unsigned int nextaddr, baseaddr, maxaddr;
288 int i;
289 int lineno;
290 int len;
291 struct ihexrec ihex;
292 int rc;
293
294 lineno = 0;
295 baseaddr = 0;
296 maxaddr = 0;
297 nextaddr = 0;
298
299 while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
300 lineno++;
301 len = strlen(buffer);
302 if (buffer[len-1] == '\n')
303 buffer[--len] = 0;
304 if (buffer[0] != ':')
305 continue;
306 rc = ihex_readrec(&ihex, buffer);
307 if (rc < 0) {
308 avrdude_message(MSG_INFO, "%s: invalid record at line %d of \"%s\"\n",
309 progname, lineno, infile);
310 return -1;
311 }
312 else if (rc != ihex.cksum) {
313 avrdude_message(MSG_INFO, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n",
314 progname, lineno, infile);
315 avrdude_message(MSG_INFO, "%s: checksum=0x%02x, computed checksum=0x%02x\n",
316 progname, ihex.cksum, rc);
317 return -1;
318 }
319
320 switch (ihex.rectyp) {
321 case 0: /* data record */
322 if (fileoffset != 0 && baseaddr < fileoffset) {
323 avrdude_message(MSG_INFO, "%s: ERROR: address 0x%04x out of range (below fileoffset 0x%x) at line %d of %s\n",
324 progname, baseaddr, fileoffset, lineno, infile);
325 return -1;
326 }
327 nextaddr = ihex.loadofs + baseaddr - fileoffset;
328 if (nextaddr + ihex.reclen > bufsize) {
329 avrdude_message(MSG_INFO, "%s: ERROR: address 0x%04x out of range at line %d of %s\n",
330 progname, nextaddr+ihex.reclen, lineno, infile);
331 return -1;
332 }
333 for (i=0; i<ihex.reclen; i++) {
334 mem->buf[nextaddr+i] = ihex.data[i];
335 mem->tags[nextaddr+i] = TAG_ALLOCATED;
336 }
337 if (nextaddr+ihex.reclen > maxaddr)
338 maxaddr = nextaddr+ihex.reclen;
339 break;
340
341 case 1: /* end of file record */
342 return maxaddr;
343 break;
344
345 case 2: /* extended segment address record */
346 baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 4;
347 break;
348
349 case 3: /* start segment address record */
350 /* we don't do anything with the start address */
351 break;
352
353 case 4: /* extended linear address record */
354 baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 16;
355 break;
356
357 case 5: /* start linear address record */
358 /* we don't do anything with the start address */
359 break;
360
361 default:
362 avrdude_message(MSG_INFO, "%s: don't know how to deal with rectype=%d "
363 "at line %d of %s\n",
364 progname, ihex.rectyp, lineno, infile);
365 return -1;
366 break;
367 }
368
369 } /* while */
370
371 if (maxaddr == 0) {
372 avrdude_message(MSG_INFO, "%s: ERROR: No valid record found in Intel Hex "
373 "file \"%s\"\n",
374 progname, infile);
375
376 return -1;
377 }
378 else {
379 avrdude_message(MSG_INFO, "%s: WARNING: no end of file record found for Intel Hex "
380 "file \"%s\"\n",
381 progname, infile);
382
383 return maxaddr;
384 }
385 }
386
b2srec(unsigned char * inbuf,int bufsize,int recsize,int startaddr,char * outfile,FILE * outf)387 static int b2srec(unsigned char * inbuf, int bufsize,
388 int recsize, int startaddr,
389 char * outfile, FILE * outf)
390 {
391 unsigned char * buf;
392 unsigned int nextaddr;
393 int n, nbytes, addr_width;
394 int i;
395 unsigned char cksum;
396
397 char * tmpl=0;
398
399 if (recsize > 255) {
400 avrdude_message(MSG_INFO, "%s: ERROR: recsize=%d, must be < 256\n",
401 progname, recsize);
402 return -1;
403 }
404
405 nextaddr = startaddr;
406 buf = inbuf;
407 nbytes = 0;
408
409 addr_width = 0;
410
411 while (bufsize) {
412
413 n = recsize;
414
415 if (n > bufsize)
416 n = bufsize;
417
418 if (n) {
419 cksum = 0;
420 if (nextaddr + n <= 0xffff) {
421 addr_width = 2;
422 tmpl="S1%02X%04X";
423 }
424 else if (nextaddr + n <= 0xffffff) {
425 addr_width = 3;
426 tmpl="S2%02X%06X";
427 }
428 else if (nextaddr + n <= 0xffffffff) {
429 addr_width = 4;
430 tmpl="S3%02X%08X";
431 }
432 else {
433 avrdude_message(MSG_INFO, "%s: ERROR: address=%d, out of range\n",
434 progname, nextaddr);
435 return -1;
436 }
437
438 fprintf(outf, tmpl, n + addr_width + 1, nextaddr);
439
440 cksum += n + addr_width + 1;
441
442 for (i=addr_width; i>0; i--)
443 cksum += (nextaddr >> (i-1) * 8) & 0xff;
444
445 for (i=nextaddr; i<nextaddr + n; i++) {
446 fprintf(outf, "%02X", buf[i]);
447 cksum += buf[i];
448 }
449
450 cksum = 0xff - cksum;
451 fprintf(outf, "%02X\n", cksum);
452
453 nextaddr += n;
454 nbytes +=n;
455 }
456
457 /* advance to next 'recsize' bytes */
458 bufsize -= n;
459 }
460
461 /*-----------------------------------------------------------------
462 add the end of record data line
463 -----------------------------------------------------------------*/
464 cksum = 0;
465 n = 0;
466 nextaddr = 0;
467
468 if (startaddr <= 0xffff) {
469 addr_width = 2;
470 tmpl="S9%02X%04X";
471 }
472 else if (startaddr <= 0xffffff) {
473 addr_width = 3;
474 tmpl="S9%02X%06X";
475 }
476 else if (startaddr <= 0xffffffff) {
477 addr_width = 4;
478 tmpl="S9%02X%08X";
479 }
480
481 fprintf(outf, tmpl, n + addr_width + 1, nextaddr);
482
483 cksum += n + addr_width +1;
484 for (i=addr_width; i>0; i--)
485 cksum += (nextaddr >> (i - 1) * 8) & 0xff;
486 cksum = 0xff - cksum;
487 fprintf(outf, "%02X\n", cksum);
488
489 return nbytes;
490 }
491
492
srec_readrec(struct ihexrec * srec,char * rec)493 static int srec_readrec(struct ihexrec * srec, char * rec)
494 {
495 int i, j;
496 char buf[8];
497 int offset, len, addr_width;
498 char * e;
499 unsigned char cksum;
500 int rc;
501
502 len = strlen(rec);
503 offset = 1;
504 cksum = 0;
505 addr_width = 2;
506
507 /* record type */
508 if (offset + 1 > len)
509 return -1;
510 srec->rectyp = rec[offset++];
511 if (srec->rectyp == 0x32 || srec->rectyp == 0x38)
512 addr_width = 3; /* S2,S8-record */
513 else if (srec->rectyp == 0x33 || srec->rectyp == 0x37)
514 addr_width = 4; /* S3,S7-record */
515
516 /* reclen */
517 if (offset + 2 > len)
518 return -1;
519 for (i=0; i<2; i++)
520 buf[i] = rec[offset++];
521 buf[i] = 0;
522 srec->reclen = strtoul(buf, &e, 16);
523 cksum += srec->reclen;
524 srec->reclen -= (addr_width+1);
525 if (e == buf || *e != 0)
526 return -1;
527
528 /* load offset */
529 if (offset + addr_width > len)
530 return -1;
531 for (i=0; i<addr_width*2; i++)
532 buf[i] = rec[offset++];
533 buf[i] = 0;
534 srec->loadofs = strtoull(buf, &e, 16);
535 if (e == buf || *e != 0)
536 return -1;
537
538 for (i=addr_width; i>0; i--)
539 cksum += (srec->loadofs >> (i - 1) * 8) & 0xff;
540
541 /* data */
542 for (j=0; j<srec->reclen; j++) {
543 if (offset+2 > len)
544 return -1;
545 for (i=0; i<2; i++)
546 buf[i] = rec[offset++];
547 buf[i] = 0;
548 srec->data[j] = strtoul(buf, &e, 16);
549 if (e == buf || *e != 0)
550 return -1;
551 cksum += srec->data[j];
552 }
553
554 /* cksum */
555 if (offset + 2 > len)
556 return -1;
557 for (i=0; i<2; i++)
558 buf[i] = rec[offset++];
559 buf[i] = 0;
560 srec->cksum = strtoul(buf, &e, 16);
561 if (e == buf || *e != 0)
562 return -1;
563
564 rc = 0xff - cksum;
565 return rc;
566 }
567
568
srec2b(char * infile,FILE * inf,AVRMEM * mem,int bufsize,unsigned int fileoffset)569 static int srec2b(char * infile, FILE * inf,
570 AVRMEM * mem, int bufsize, unsigned int fileoffset)
571 {
572 char buffer [ MAX_LINE_LEN ];
573 unsigned int nextaddr, maxaddr;
574 int i;
575 int lineno;
576 int len;
577 struct ihexrec srec;
578 int rc;
579 int reccount;
580 unsigned char datarec;
581
582 char * msg = 0;
583
584 lineno = 0;
585 maxaddr = 0;
586 reccount = 0;
587
588 while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
589 lineno++;
590 len = strlen(buffer);
591 if (buffer[len-1] == '\n')
592 buffer[--len] = 0;
593 if (buffer[0] != 0x53)
594 continue;
595 rc = srec_readrec(&srec, buffer);
596
597 if (rc < 0) {
598 avrdude_message(MSG_INFO, "%s: ERROR: invalid record at line %d of \"%s\"\n",
599 progname, lineno, infile);
600 return -1;
601 }
602 else if (rc != srec.cksum) {
603 avrdude_message(MSG_INFO, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n",
604 progname, lineno, infile);
605 avrdude_message(MSG_INFO, "%s: checksum=0x%02x, computed checksum=0x%02x\n",
606 progname, srec.cksum, rc);
607 return -1;
608 }
609
610 datarec=0;
611 switch (srec.rectyp) {
612 case 0x30: /* S0 - header record*/
613 /* skip */
614 break;
615
616 case 0x31: /* S1 - 16 bit address data record */
617 datarec=1;
618 msg="%s: ERROR: address 0x%04x out of range %sat line %d of %s\n";
619 break;
620
621 case 0x32: /* S2 - 24 bit address data record */
622 datarec=1;
623 msg="%s: ERROR: address 0x%06x out of range %sat line %d of %s\n";
624 break;
625
626 case 0x33: /* S3 - 32 bit address data record */
627 datarec=1;
628 msg="%s: ERROR: address 0x%08x out of range %sat line %d of %s\n";
629 break;
630
631 case 0x34: /* S4 - symbol record (LSI extension) */
632 avrdude_message(MSG_INFO, "%s: ERROR: not supported record at line %d of %s\n",
633 progname, lineno, infile);
634 return -1;
635
636 case 0x35: /* S5 - count of S1,S2 and S3 records previously tx'd */
637 if (srec.loadofs != reccount){
638 avrdude_message(MSG_INFO, "%s: ERROR: count of transmitted data records mismatch "
639 "at line %d of \"%s\"\n",
640 progname, lineno, infile);
641 avrdude_message(MSG_INFO, "%s: transmitted data records= %d, expected "
642 "value= %d\n",
643 progname, reccount, srec.loadofs);
644 return -1;
645 }
646 break;
647
648 case 0x37: /* S7 Record - end record for 32 bit address data */
649 case 0x38: /* S8 Record - end record for 24 bit address data */
650 case 0x39: /* S9 Record - end record for 16 bit address data */
651 return maxaddr;
652
653 default:
654 avrdude_message(MSG_INFO, "%s: ERROR: don't know how to deal with rectype S%d "
655 "at line %d of %s\n",
656 progname, srec.rectyp, lineno, infile);
657 return -1;
658 }
659
660 if (datarec == 1) {
661 nextaddr = srec.loadofs;
662 if (nextaddr < fileoffset) {
663 avrdude_message(MSG_INFO, msg, progname, nextaddr,
664 "(below fileoffset) ",
665 lineno, infile);
666 return -1;
667 }
668 nextaddr -= fileoffset;
669 if (nextaddr + srec.reclen > bufsize) {
670 avrdude_message(MSG_INFO, msg, progname, nextaddr+srec.reclen, "",
671 lineno, infile);
672 return -1;
673 }
674 for (i=0; i<srec.reclen; i++) {
675 mem->buf[nextaddr+i] = srec.data[i];
676 mem->tags[nextaddr+i] = TAG_ALLOCATED;
677 }
678 if (nextaddr+srec.reclen > maxaddr)
679 maxaddr = nextaddr+srec.reclen;
680 reccount++;
681 }
682
683 }
684
685 avrdude_message(MSG_INFO, "%s: WARNING: no end of file record found for Motorola S-Records "
686 "file \"%s\"\n",
687 progname, infile);
688
689 return maxaddr;
690 }
691
692 #ifdef HAVE_LIBELF
693 /*
694 * Determine whether the ELF file section pointed to by `sh' fits
695 * completely into the program header segment pointed to by `ph'.
696 *
697 * Assumes the section has been checked already before to actually
698 * contain data (SHF_ALLOC, SHT_PROGBITS, sh_size > 0).
699 *
700 * Sometimes, program header segments might be larger than the actual
701 * file sections. On VM architectures, this is used to allow mmapping
702 * the entire ELF file "as is" (including things like the program
703 * header table itself).
704 */
705 static inline
is_section_in_segment(Elf32_Shdr * sh,Elf32_Phdr * ph)706 int is_section_in_segment(Elf32_Shdr *sh, Elf32_Phdr *ph)
707 {
708 if (sh->sh_offset < ph->p_offset)
709 return 0;
710 if (sh->sh_offset + sh->sh_size > ph->p_offset + ph->p_filesz)
711 return 0;
712 return 1;
713 }
714
715 /*
716 * Return the ELF section descriptor that corresponds to program
717 * header `ph'. The program header is expected to be of p_type
718 * PT_LOAD, and to have a nonzero p_filesz. (PT_LOAD sections with a
719 * zero p_filesz are typically RAM sections that are not initialized
720 * by file data, e.g. ".bss".)
721 */
elf_get_scn(Elf * e,Elf32_Phdr * ph,Elf32_Shdr ** shptr)722 static Elf_Scn *elf_get_scn(Elf *e, Elf32_Phdr *ph, Elf32_Shdr **shptr)
723 {
724 Elf_Scn *s = NULL;
725
726 while ((s = elf_nextscn(e, s)) != NULL) {
727 Elf32_Shdr *sh;
728 size_t ndx = elf_ndxscn(s);
729 if ((sh = elf32_getshdr(s)) == NULL) {
730 avrdude_message(MSG_INFO, "%s: ERROR: Error reading section #%u header: %s\n",
731 progname, (unsigned int)ndx, elf_errmsg(-1));
732 continue;
733 }
734 if ((sh->sh_flags & SHF_ALLOC) == 0 ||
735 sh->sh_type != SHT_PROGBITS)
736 /* we are only interested in PROGBITS, ALLOC sections */
737 continue;
738 if (sh->sh_size == 0)
739 /* we are not interested in empty sections */
740 continue;
741 if (is_section_in_segment(sh, ph)) {
742 /* yeah, we found it */
743 *shptr = sh;
744 return s;
745 }
746 }
747
748 avrdude_message(MSG_INFO, "%s: ERROR: Cannot find a matching section for "
749 "program header entry @p_vaddr 0x%x\n",
750 progname, ph->p_vaddr);
751 return NULL;
752 }
753
elf_mem_limits(AVRMEM * mem,struct avrpart * p,unsigned int * lowbound,unsigned int * highbound,unsigned int * fileoff)754 static int elf_mem_limits(AVRMEM *mem, struct avrpart * p,
755 unsigned int *lowbound,
756 unsigned int *highbound,
757 unsigned int *fileoff)
758 {
759 int rv = 0;
760
761 if (p->flags & AVRPART_AVR32) {
762 if (strcmp(mem->desc, "flash") == 0) {
763 *lowbound = 0x80000000;
764 *highbound = 0xffffffff;
765 *fileoff = 0;
766 } else {
767 rv = -1;
768 }
769 } else {
770 if (strcmp(mem->desc, "flash") == 0 ||
771 strcmp(mem->desc, "boot") == 0 ||
772 strcmp(mem->desc, "application") == 0 ||
773 strcmp(mem->desc, "apptable") == 0) {
774 *lowbound = 0;
775 *highbound = 0x7ffff; /* max 8 MiB */
776 *fileoff = 0;
777 } else if (strcmp(mem->desc, "eeprom") == 0) {
778 *lowbound = 0x810000;
779 *highbound = 0x81ffff; /* max 64 KiB */
780 *fileoff = 0;
781 } else if (strcmp(mem->desc, "lfuse") == 0) {
782 *lowbound = 0x820000;
783 *highbound = 0x82ffff;
784 *fileoff = 0;
785 } else if (strcmp(mem->desc, "hfuse") == 0) {
786 *lowbound = 0x820000;
787 *highbound = 0x82ffff;
788 *fileoff = 1;
789 } else if (strcmp(mem->desc, "efuse") == 0) {
790 *lowbound = 0x820000;
791 *highbound = 0x82ffff;
792 *fileoff = 2;
793 } else if (strncmp(mem->desc, "fuse", 4) == 0 &&
794 (mem->desc[4] >= '0' && mem->desc[4] <= '9')) {
795 /* Xmega fuseN */
796 *lowbound = 0x820000;
797 *highbound = 0x82ffff;
798 *fileoff = mem->desc[4] - '0';
799 } else if (strncmp(mem->desc, "lock", 4) == 0) {
800 *lowbound = 0x830000;
801 *highbound = 0x83ffff;
802 *fileoff = 0;
803 } else {
804 rv = -1;
805 }
806 }
807
808 return rv;
809 }
810
811
elf2b(char * infile,FILE * inf,AVRMEM * mem,struct avrpart * p,int bufsize,unsigned int fileoffset)812 static int elf2b(char * infile, FILE * inf,
813 AVRMEM * mem, struct avrpart * p,
814 int bufsize, unsigned int fileoffset)
815 {
816 Elf *e;
817 int rv = -1;
818 unsigned int low, high, foff;
819
820 if (elf_mem_limits(mem, p, &low, &high, &foff) != 0) {
821 avrdude_message(MSG_INFO, "%s: ERROR: Cannot handle \"%s\" memory region from ELF file\n",
822 progname, mem->desc);
823 return -1;
824 }
825
826 /*
827 * The Xmega memory regions for "boot", "application", and
828 * "apptable" are actually sub-regions of "flash". Refine the
829 * applicable limits. This allows to select only the appropriate
830 * sections out of an ELF file that contains section data for more
831 * than one sub-segment.
832 */
833 if ((p->flags & AVRPART_HAS_PDI) != 0 &&
834 (strcmp(mem->desc, "boot") == 0 ||
835 strcmp(mem->desc, "application") == 0 ||
836 strcmp(mem->desc, "apptable") == 0)) {
837 AVRMEM *flashmem = avr_locate_mem(p, "flash");
838 if (flashmem == NULL) {
839 avrdude_message(MSG_INFO, "%s: ERROR: No \"flash\" memory region found, "
840 "cannot compute bounds of \"%s\" sub-region.\n",
841 progname, mem->desc);
842 return -1;
843 }
844 /* The config file offsets are PDI offsets, rebase to 0. */
845 low = mem->offset - flashmem->offset;
846 high = low + mem->size - 1;
847 }
848
849 if (elf_version(EV_CURRENT) == EV_NONE) {
850 avrdude_message(MSG_INFO, "%s: ERROR: ELF library initialization failed: %s\n",
851 progname, elf_errmsg(-1));
852 return -1;
853 }
854 if ((e = elf_begin(fileno(inf), ELF_C_READ, NULL)) == NULL) {
855 avrdude_message(MSG_INFO, "%s: ERROR: Cannot open \"%s\" as an ELF file: %s\n",
856 progname, infile, elf_errmsg(-1));
857 return -1;
858 }
859 if (elf_kind(e) != ELF_K_ELF) {
860 avrdude_message(MSG_INFO, "%s: ERROR: Cannot use \"%s\" as an ELF input file\n",
861 progname, infile);
862 goto done;
863 }
864
865 size_t i, isize;
866 const char *id = elf_getident(e, &isize);
867
868 if (id == NULL) {
869 avrdude_message(MSG_INFO, "%s: ERROR: Error reading ident area of \"%s\": %s\n",
870 progname, infile, elf_errmsg(-1));
871 goto done;
872 }
873
874 const char *endianname;
875 unsigned char endianess;
876 if (p->flags & AVRPART_AVR32) {
877 endianess = ELFDATA2MSB;
878 endianname = "little";
879 } else {
880 endianess = ELFDATA2LSB;
881 endianname = "big";
882 }
883 if (id[EI_CLASS] != ELFCLASS32 ||
884 id[EI_DATA] != endianess) {
885 avrdude_message(MSG_INFO, "%s: ERROR: ELF file \"%s\" is not a "
886 "32-bit, %s-endian file that was expected\n",
887 progname, infile, endianname);
888 goto done;
889 }
890
891 Elf32_Ehdr *eh;
892 if ((eh = elf32_getehdr(e)) == NULL) {
893 avrdude_message(MSG_INFO, "%s: ERROR: Error reading ehdr of \"%s\": %s\n",
894 progname, infile, elf_errmsg(-1));
895 goto done;
896 }
897
898 if (eh->e_type != ET_EXEC) {
899 avrdude_message(MSG_INFO, "%s: ERROR: ELF file \"%s\" is not an executable file\n",
900 progname, infile);
901 goto done;
902 }
903
904 const char *mname;
905 uint16_t machine;
906 if (p->flags & AVRPART_AVR32) {
907 machine = EM_AVR32;
908 mname = "AVR32";
909 } else {
910 machine = EM_AVR;
911 mname = "AVR";
912 }
913 if (eh->e_machine != machine) {
914 avrdude_message(MSG_INFO, "%s: ERROR: ELF file \"%s\" is not for machine %s\n",
915 progname, infile, mname);
916 goto done;
917 }
918 if (eh->e_phnum == 0xffff /* PN_XNUM */) {
919 avrdude_message(MSG_INFO, "%s: ERROR: ELF file \"%s\" uses extended "
920 "program header numbers which are not expected\n",
921 progname, infile);
922 goto done;
923 }
924
925 Elf32_Phdr *ph;
926 if ((ph = elf32_getphdr(e)) == NULL) {
927 avrdude_message(MSG_INFO, "%s: ERROR: Error reading program header table of \"%s\": %s\n",
928 progname, infile, elf_errmsg(-1));
929 goto done;
930 }
931
932 size_t sndx;
933 if (elf_getshdrstrndx(e, &sndx) != 0) {
934 avrdude_message(MSG_INFO, "%s: ERROR: Error obtaining section name string table: %s\n",
935 progname, elf_errmsg(-1));
936 sndx = 0;
937 }
938
939 /*
940 * Walk the program header table, pick up entries that are of type
941 * PT_LOAD, and have a non-zero p_filesz.
942 */
943 for (i = 0; i < eh->e_phnum; i++) {
944 if (ph[i].p_type != PT_LOAD ||
945 ph[i].p_filesz == 0)
946 continue;
947
948 avrdude_message(MSG_NOTICE2, "%s: Considering PT_LOAD program header entry #%d:\n"
949 " p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n",
950 progname, i, ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz);
951
952 Elf32_Shdr *sh;
953 Elf_Scn *s = elf_get_scn(e, ph + i, &sh);
954 if (s == NULL)
955 continue;
956
957 if ((sh->sh_flags & SHF_ALLOC) && sh->sh_size) {
958 const char *sname;
959
960 if (sndx != 0) {
961 sname = elf_strptr(e, sndx, sh->sh_name);
962 } else {
963 sname = "*unknown*";
964 }
965
966 unsigned int lma;
967 lma = ph[i].p_paddr + sh->sh_offset - ph[i].p_offset;
968
969 avrdude_message(MSG_NOTICE2, "%s: Found section \"%s\", LMA 0x%x, sh_size %u\n",
970 progname, sname, lma, sh->sh_size);
971
972 if (lma >= low &&
973 lma + sh->sh_size < high) {
974 /* OK */
975 } else {
976 avrdude_message(MSG_NOTICE2, " => skipping, inappropriate for \"%s\" memory region\n",
977 mem->desc);
978 continue;
979 }
980 /*
981 * 1-byte sized memory regions are special: they are used for fuse
982 * bits, where multiple regions (in the config file) map to a
983 * single, larger region in the ELF file (e.g. "lfuse", "hfuse",
984 * and "efuse" all map to ".fuse"). We silently accept a larger
985 * ELF file region for these, and extract the actual byte to write
986 * from it, using the "foff" offset obtained above.
987 */
988 if (mem->size != 1 &&
989 sh->sh_size > mem->size) {
990 avrdude_message(MSG_INFO, "%s: ERROR: section \"%s\" does not fit into \"%s\" memory:\n"
991 " 0x%x + %u > %u\n",
992 progname, sname, mem->desc,
993 lma, sh->sh_size, mem->size);
994 continue;
995 }
996
997 Elf_Data *d = NULL;
998 while ((d = elf_getdata(s, d)) != NULL) {
999 avrdude_message(MSG_NOTICE2, " Data block: d_buf %p, d_off 0x%x, d_size %d\n",
1000 d->d_buf, (unsigned int)d->d_off, d->d_size);
1001 if (mem->size == 1) {
1002 if (d->d_off != 0) {
1003 avrdude_message(MSG_INFO, "%s: ERROR: unexpected data block at offset != 0\n",
1004 progname);
1005 } else if (foff >= d->d_size) {
1006 avrdude_message(MSG_INFO, "%s: ERROR: ELF file section does not contain byte at offset %d\n",
1007 progname, foff);
1008 } else {
1009 avrdude_message(MSG_NOTICE2, " Extracting one byte from file offset %d\n",
1010 foff);
1011 mem->buf[0] = ((unsigned char *)d->d_buf)[foff];
1012 mem->tags[0] = TAG_ALLOCATED;
1013 rv = 1;
1014 }
1015 } else {
1016 unsigned int idx;
1017
1018 idx = lma - low + d->d_off;
1019 if ((int)(idx + d->d_size) > rv)
1020 rv = idx + d->d_size;
1021 avrdude_message(MSG_DEBUG, " Writing %d bytes to mem offset 0x%x\n",
1022 d->d_size, idx);
1023 memcpy(mem->buf + idx, d->d_buf, d->d_size);
1024 memset(mem->tags + idx, TAG_ALLOCATED, d->d_size);
1025 }
1026 }
1027 }
1028 }
1029 done:
1030 (void)elf_end(e);
1031 return rv;
1032 }
1033 #endif /* HAVE_LIBELF */
1034
1035 /*
1036 * Simple itoa() implementation. Caller needs to allocate enough
1037 * space in buf. Only positive integers are handled.
1038 */
itoa_simple(int n,char * buf,int base)1039 static char *itoa_simple(int n, char *buf, int base)
1040 {
1041 div_t q;
1042 char c, *cp, *cp2;
1043
1044 cp = buf;
1045 /*
1046 * Divide by base until the number disappeared, but ensure at least
1047 * one digit will be emitted.
1048 */
1049 do {
1050 q = div(n, base);
1051 n = q.quot;
1052 if (q.rem >= 10)
1053 c = q.rem - 10 + 'a';
1054 else
1055 c = q.rem + '0';
1056 *cp++ = c;
1057 } while (q.quot != 0);
1058
1059 /* Terminate the string. */
1060 *cp-- = '\0';
1061
1062 /* Now revert the result string. */
1063 cp2 = buf;
1064 while (cp > cp2) {
1065 c = *cp;
1066 *cp-- = *cp2;
1067 *cp2++ = c;
1068 }
1069
1070 return buf;
1071 }
1072
1073
1074
fileio_rbin(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,int size)1075 static int fileio_rbin(struct fioparms * fio,
1076 char * filename, FILE * f, AVRMEM * mem, int size)
1077 {
1078 int rc;
1079 unsigned char *buf = mem->buf;
1080
1081 switch (fio->op) {
1082 case FIO_READ:
1083 rc = fread(buf, 1, size, f);
1084 if (rc > 0)
1085 memset(mem->tags, TAG_ALLOCATED, rc);
1086 break;
1087 case FIO_WRITE:
1088 rc = fwrite(buf, 1, size, f);
1089 break;
1090 default:
1091 avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
1092 progname, fio->op);
1093 return -1;
1094 }
1095
1096 if (rc < 0 || (fio->op == FIO_WRITE && rc < size)) {
1097 avrdude_message(MSG_INFO, "%s: %s error %s %s: %s; %s %d of the expected %d bytes\n",
1098 progname, fio->iodesc, fio->dir, filename, strerror(errno),
1099 fio->rw, rc, size);
1100 return -1;
1101 }
1102
1103 return rc;
1104 }
1105
1106
fileio_imm(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,int size)1107 static int fileio_imm(struct fioparms * fio,
1108 char * filename, FILE * f, AVRMEM * mem, int size)
1109 {
1110 int rc = 0;
1111 char * e, * p;
1112 unsigned long b;
1113 int loc;
1114
1115 switch (fio->op) {
1116 case FIO_READ:
1117 loc = 0;
1118 p = strtok(filename, " ,");
1119 while (p != NULL && loc < size) {
1120 b = strtoul(p, &e, 0);
1121 /* check for binary formated (0b10101001) strings */
1122 b = (strncmp (p, "0b", 2))?
1123 strtoul (p, &e, 0):
1124 strtoul (p + 2, &e, 2);
1125 if (*e != 0) {
1126 avrdude_message(MSG_INFO, "%s: invalid byte value (%s) specified for immediate mode\n",
1127 progname, p);
1128 return -1;
1129 }
1130 mem->buf[loc] = b;
1131 mem->tags[loc++] = TAG_ALLOCATED;
1132 p = strtok(NULL, " ,");
1133 rc = loc;
1134 }
1135 break;
1136 default:
1137 avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
1138 progname, fio->op);
1139 return -1;
1140 }
1141
1142 if (rc < 0 || (fio->op == FIO_WRITE && rc < size)) {
1143 avrdude_message(MSG_INFO, "%s: %s error %s %s: %s; %s %d of the expected %d bytes\n",
1144 progname, fio->iodesc, fio->dir, filename, strerror(errno),
1145 fio->rw, rc, size);
1146 return -1;
1147 }
1148
1149 return rc;
1150 }
1151
1152
fileio_ihex(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,int size)1153 static int fileio_ihex(struct fioparms * fio,
1154 char * filename, FILE * f, AVRMEM * mem, int size)
1155 {
1156 int rc;
1157
1158 switch (fio->op) {
1159 case FIO_WRITE:
1160 rc = b2ihex(mem->buf, size, 32, fio->fileoffset, filename, f);
1161 if (rc < 0) {
1162 return -1;
1163 }
1164 break;
1165
1166 case FIO_READ:
1167 rc = ihex2b(filename, f, mem, size, fio->fileoffset);
1168 if (rc < 0)
1169 return -1;
1170 break;
1171
1172 default:
1173 avrdude_message(MSG_INFO, "%s: invalid Intex Hex file I/O operation=%d\n",
1174 progname, fio->op);
1175 return -1;
1176 break;
1177 }
1178
1179 return rc;
1180 }
1181
1182
fileio_srec(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,int size)1183 static int fileio_srec(struct fioparms * fio,
1184 char * filename, FILE * f, AVRMEM * mem, int size)
1185 {
1186 int rc;
1187
1188 switch (fio->op) {
1189 case FIO_WRITE:
1190 rc = b2srec(mem->buf, size, 32, fio->fileoffset, filename, f);
1191 if (rc < 0) {
1192 return -1;
1193 }
1194 break;
1195
1196 case FIO_READ:
1197 rc = srec2b(filename, f, mem, size, fio->fileoffset);
1198 if (rc < 0)
1199 return -1;
1200 break;
1201
1202 default:
1203 avrdude_message(MSG_INFO, "%s: ERROR: invalid Motorola S-Records file I/O "
1204 "operation=%d\n",
1205 progname, fio->op);
1206 return -1;
1207 break;
1208 }
1209
1210 return rc;
1211 }
1212
1213
1214 #ifdef HAVE_LIBELF
fileio_elf(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,struct avrpart * p,int size)1215 static int fileio_elf(struct fioparms * fio,
1216 char * filename, FILE * f, AVRMEM * mem,
1217 struct avrpart * p, int size)
1218 {
1219 int rc;
1220
1221 switch (fio->op) {
1222 case FIO_WRITE:
1223 avrdude_message(MSG_INFO, "%s: ERROR: write operation not (yet) "
1224 "supported for ELF\n",
1225 progname);
1226 return -1;
1227 break;
1228
1229 case FIO_READ:
1230 rc = elf2b(filename, f, mem, p, size, fio->fileoffset);
1231 return rc;
1232
1233 default:
1234 avrdude_message(MSG_INFO, "%s: ERROR: invalid ELF file I/O "
1235 "operation=%d\n",
1236 progname, fio->op);
1237 return -1;
1238 break;
1239 }
1240 }
1241
1242 #endif
1243
fileio_num(struct fioparms * fio,char * filename,FILE * f,AVRMEM * mem,int size,FILEFMT fmt)1244 static int fileio_num(struct fioparms * fio,
1245 char * filename, FILE * f, AVRMEM * mem, int size,
1246 FILEFMT fmt)
1247 {
1248 const char *prefix;
1249 char cbuf[20];
1250 int base, i, num;
1251
1252 switch (fmt) {
1253 case FMT_HEX:
1254 prefix = "0x";
1255 base = 16;
1256 break;
1257
1258 default:
1259 case FMT_DEC:
1260 prefix = "";
1261 base = 10;
1262 break;
1263
1264 case FMT_OCT:
1265 prefix = "0";
1266 base = 8;
1267 break;
1268
1269 case FMT_BIN:
1270 prefix = "0b";
1271 base = 2;
1272 break;
1273
1274 }
1275
1276 switch (fio->op) {
1277 case FIO_WRITE:
1278 break;
1279 default:
1280 avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
1281 progname, fio->op);
1282 return -1;
1283 }
1284
1285 for (i = 0; i < size; i++) {
1286 if (i > 0) {
1287 if (putc(',', f) == EOF)
1288 goto writeerr;
1289 }
1290 num = (unsigned int)(mem->buf[i]);
1291 /*
1292 * For a base of 8 and a value < 8 to convert, don't write the
1293 * prefix. The conversion will be indistinguishable from a
1294 * decimal one then.
1295 */
1296 if (prefix[0] != '\0' && !(base == 8 && num < 8)) {
1297 if (fputs(prefix, f) == EOF)
1298 goto writeerr;
1299 }
1300 itoa_simple(num, cbuf, base);
1301 if (fputs(cbuf, f) == EOF)
1302 goto writeerr;
1303 }
1304 if (putc('\n', f) == EOF)
1305 goto writeerr;
1306
1307 return 0;
1308
1309 writeerr:
1310 avrdude_message(MSG_INFO, "%s: error writing to %s: %s\n",
1311 progname, filename, strerror(errno));
1312 return -1;
1313 }
1314
1315
fileio_setparms(int op,struct fioparms * fp,struct avrpart * p,AVRMEM * m)1316 int fileio_setparms(int op, struct fioparms * fp,
1317 struct avrpart * p, AVRMEM * m)
1318 {
1319 fp->op = op;
1320
1321 switch (op) {
1322 case FIO_READ:
1323 fp->mode = "r";
1324 fp->iodesc = "input";
1325 fp->dir = "from";
1326 fp->rw = "read";
1327 break;
1328
1329 case FIO_WRITE:
1330 fp->mode = "w";
1331 fp->iodesc = "output";
1332 fp->dir = "to";
1333 fp->rw = "wrote";
1334 break;
1335
1336 default:
1337 avrdude_message(MSG_INFO, "%s: invalid I/O operation %d\n",
1338 progname, op);
1339 return -1;
1340 break;
1341 }
1342
1343 /*
1344 * AVR32 devices maintain their load offset within the file itself,
1345 * but AVRDUDE maintains all memory images 0-based.
1346 */
1347 if ((p->flags & AVRPART_AVR32) != 0)
1348 {
1349 fp->fileoffset = m->offset;
1350 }
1351 else
1352 {
1353 fp->fileoffset = 0;
1354 }
1355
1356 return 0;
1357 }
1358
1359
1360
fmt_autodetect(char * fname)1361 static int fmt_autodetect(char * fname)
1362 {
1363 FILE * f;
1364 unsigned char buf[MAX_LINE_LEN];
1365 int i;
1366 int len;
1367 int found;
1368 int first = 1;
1369
1370 #if defined(WIN32NATIVE)
1371 f = fopen(fname, "r");
1372 #else
1373 f = fopen(fname, "rb");
1374 #endif
1375 if (f == NULL) {
1376 avrdude_message(MSG_INFO, "%s: error opening %s: %s\n",
1377 progname, fname, strerror(errno));
1378 return -1;
1379 }
1380
1381 while (fgets((char *)buf, MAX_LINE_LEN, f)!=NULL) {
1382 /* check for ELF file */
1383 if (first &&
1384 (buf[0] == 0177 && buf[1] == 'E' &&
1385 buf[2] == 'L' && buf[3] == 'F')) {
1386 fclose(f);
1387 return FMT_ELF;
1388 }
1389
1390 buf[MAX_LINE_LEN-1] = 0;
1391 len = strlen((char *)buf);
1392 if (buf[len-1] == '\n')
1393 buf[--len] = 0;
1394
1395 /* check for binary data */
1396 found = 0;
1397 for (i=0; i<len; i++) {
1398 if (buf[i] > 127) {
1399 found = 1;
1400 break;
1401 }
1402 }
1403 if (found) {
1404 fclose(f);
1405 return FMT_RBIN;
1406 }
1407
1408 /* check for lines that look like intel hex */
1409 if ((buf[0] == ':') && (len >= 11)) {
1410 found = 1;
1411 for (i=1; i<len; i++) {
1412 if (!isxdigit(buf[1])) {
1413 found = 0;
1414 break;
1415 }
1416 }
1417 if (found) {
1418 fclose(f);
1419 return FMT_IHEX;
1420 }
1421 }
1422
1423 /* check for lines that look like motorola s-record */
1424 if ((buf[0] == 'S') && (len >= 10) && isdigit(buf[1])) {
1425 found = 1;
1426 for (i=1; i<len; i++) {
1427 if (!isxdigit(buf[1])) {
1428 found = 0;
1429 break;
1430 }
1431 }
1432 if (found) {
1433 fclose(f);
1434 return FMT_SREC;
1435 }
1436 }
1437
1438 first = 0;
1439 }
1440
1441 fclose(f);
1442 return -1;
1443 }
1444
1445
1446
fileio(int op,char * filename,FILEFMT format,struct avrpart * p,char * memtype,int size)1447 int fileio(int op, char * filename, FILEFMT format,
1448 struct avrpart * p, char * memtype, int size)
1449 {
1450 int rc;
1451 FILE * f;
1452 char * fname;
1453 struct fioparms fio;
1454 AVRMEM * mem;
1455 int using_stdio;
1456
1457 mem = avr_locate_mem(p, memtype);
1458 if (mem == NULL) {
1459 avrdude_message(MSG_INFO, "fileio(): memory type \"%s\" not configured for device \"%s\"\n",
1460 memtype, p->desc);
1461 return -1;
1462 }
1463
1464 rc = fileio_setparms(op, &fio, p, mem);
1465 if (rc < 0)
1466 return -1;
1467
1468 if (fio.op == FIO_READ)
1469 size = mem->size;
1470
1471 if (fio.op == FIO_READ) {
1472 /* 0xff fill unspecified memory */
1473 memset(mem->buf, 0xff, size);
1474 }
1475 memset(mem->tags, 0, size);
1476
1477 using_stdio = 0;
1478
1479 if (strcmp(filename, "-")==0) {
1480 if (fio.op == FIO_READ) {
1481 fname = "<stdin>";
1482 f = stdin;
1483 }
1484 else {
1485 fname = "<stdout>";
1486 f = stdout;
1487 }
1488 using_stdio = 1;
1489 }
1490 else {
1491 fname = filename;
1492 f = NULL;
1493 }
1494
1495 if (format == FMT_AUTO) {
1496 int format_detect;
1497
1498 if (using_stdio) {
1499 avrdude_message(MSG_INFO, "%s: can't auto detect file format when using stdin/out.\n"
1500 "%s Please specify a file format and try again.\n",
1501 progname, progbuf);
1502 return -1;
1503 }
1504
1505 format_detect = fmt_autodetect(fname);
1506 if (format_detect < 0) {
1507 avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
1508 progname, fname);
1509 return -1;
1510 }
1511 format = format_detect;
1512
1513 if (quell_progress < 2) {
1514 avrdude_message(MSG_INFO, "%s: %s file %s auto detected as %s\n",
1515 progname, fio.iodesc, fname, fmtstr(format));
1516 }
1517 }
1518
1519 #if defined(WIN32NATIVE)
1520 /* Open Raw Binary and ELF format in binary mode on Windows.*/
1521 if(format == FMT_RBIN || format == FMT_ELF)
1522 {
1523 if(fio.op == FIO_READ)
1524 {
1525 fio.mode = "rb";
1526 }
1527 if(fio.op == FIO_WRITE)
1528 {
1529 fio.mode = "wb";
1530 }
1531 }
1532 #endif
1533
1534 if (format != FMT_IMM) {
1535 if (!using_stdio) {
1536 f = fopen(fname, fio.mode);
1537 if (f == NULL) {
1538 avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
1539 progname, fio.iodesc, fname, strerror(errno));
1540 return -1;
1541 }
1542 }
1543 }
1544
1545 switch (format) {
1546 case FMT_IHEX:
1547 rc = fileio_ihex(&fio, fname, f, mem, size);
1548 break;
1549
1550 case FMT_SREC:
1551 rc = fileio_srec(&fio, fname, f, mem, size);
1552 break;
1553
1554 case FMT_RBIN:
1555 rc = fileio_rbin(&fio, fname, f, mem, size);
1556 break;
1557
1558 case FMT_ELF:
1559 #ifdef HAVE_LIBELF
1560 rc = fileio_elf(&fio, fname, f, mem, p, size);
1561 #else
1562 avrdude_message(MSG_INFO, "%s: can't handle ELF file %s, "
1563 "ELF file support was not compiled in\n",
1564 progname, fname);
1565 rc = -1;
1566 #endif
1567 break;
1568
1569 case FMT_IMM:
1570 rc = fileio_imm(&fio, fname, f, mem, size);
1571 break;
1572
1573 case FMT_HEX:
1574 case FMT_DEC:
1575 case FMT_OCT:
1576 case FMT_BIN:
1577 rc = fileio_num(&fio, fname, f, mem, size, format);
1578 break;
1579
1580 default:
1581 avrdude_message(MSG_INFO, "%s: invalid %s file format: %d\n",
1582 progname, fio.iodesc, format);
1583 return -1;
1584 }
1585
1586 if (rc > 0) {
1587 if ((op == FIO_READ) && (strcasecmp(mem->desc, "flash") == 0 ||
1588 strcasecmp(mem->desc, "application") == 0 ||
1589 strcasecmp(mem->desc, "apptable") == 0 ||
1590 strcasecmp(mem->desc, "boot") == 0)) {
1591 /*
1592 * if we are reading flash, just mark the size as being the
1593 * highest non-0xff byte
1594 */
1595 rc = avr_mem_hiaddr(mem);
1596 }
1597 }
1598 if (format != FMT_IMM && !using_stdio) {
1599 fclose(f);
1600 }
1601
1602 return rc;
1603 }
1604
1605