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