1 /*
2  * avrdude - A Downloader/Uploader for AVR device programmers
3  * Copyright (C) 2000-2005  Brian S. Dean <bsd@bsdhome.com>
4  * Copyright (C) 2007 Joerg Wunsch
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, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /* $Id$ */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <time.h>
27 
28 #include "avrdude.h"
29 #include "libavrdude.h"
30 
parse_op(char * s)31 UPDATE * parse_op(char * s)
32 {
33   char buf[1024];
34   char * p, * cp, c;
35   UPDATE * upd;
36   int i;
37   size_t fnlen;
38 
39   upd = (UPDATE *)malloc(sizeof(UPDATE));
40   if (upd == NULL) {
41     // avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
42     // exit(1);
43     avrdude_oom("parse_op: out of memory\n");
44   }
45 
46   i = 0;
47   p = s;
48   while ((i < (sizeof(buf)-1) && *p && (*p != ':')))
49     buf[i++] = *p++;
50   buf[i] = 0;
51 
52   if (*p != ':') {
53     upd->memtype = NULL;        /* default memtype, "flash", or "application" */
54     upd->op = DEVICE_WRITE;
55     upd->filename = (char *)malloc(strlen(buf) + 1);
56     if (upd->filename == NULL) {
57         // avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
58         // exit(1);
59         avrdude_oom("parse_op: out of memory\n");
60     }
61     strcpy(upd->filename, buf);
62     upd->format = FMT_AUTO;
63     return upd;
64   }
65 
66   upd->memtype = (char *)malloc(strlen(buf)+1);
67   if (upd->memtype == NULL) {
68     // avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
69     // exit(1);
70     avrdude_oom("parse_op: out of memory\n");
71   }
72   strcpy(upd->memtype, buf);
73 
74   p++;
75   if (*p == 'r') {
76     upd->op = DEVICE_READ;
77   }
78   else if (*p == 'w') {
79     upd->op = DEVICE_WRITE;
80   }
81   else if (*p == 'v') {
82     upd->op = DEVICE_VERIFY;
83   }
84   else {
85     avrdude_message(MSG_INFO, "%s: invalid I/O mode '%c' in update specification\n",
86             progname, *p);
87     avrdude_message(MSG_INFO, "  allowed values are:\n"
88                     "    r = read device\n"
89                     "    w = write device\n"
90                     "    v = verify device\n");
91     free(upd->memtype);
92     free(upd);
93     return NULL;
94   }
95 
96   p++;
97 
98   if (*p != ':') {
99     avrdude_message(MSG_INFO, "%s: invalid update specification\n", progname);
100     free(upd->memtype);
101     free(upd);
102     return NULL;
103   }
104 
105   p++;
106 
107   // Extension: Parse file section number
108   unsigned section = 0;
109 
110   for (; *p != ':'; p++) {
111     if (*p >= '0' && *p <= '9') {
112       section *= 10;
113       section += *p - 0x30;
114     } else {
115       avrdude_message(MSG_INFO, "%s: invalid update specification: <section> is not a number\n", progname);
116       free(upd->memtype);
117       free(upd);
118       return NULL;
119     }
120   }
121 
122   upd->section = section;
123   p++;
124 
125   /*
126    * Now, parse the filename component.  Instead of looking for the
127    * leftmost possible colon delimiter, we look for the rightmost one.
128    * If we found one, we do have a trailing :format specifier, and
129    * process it.  Otherwise, the remainder of the string is our file
130    * name component.  That way, the file name itself is allowed to
131    * contain a colon itself (e. g. C:/some/file.hex), except the
132    * optional format specifier becomes mandatory then.
133    */
134   cp = p;
135   p = strrchr(cp, ':');
136   if (p == NULL) {
137     upd->format = FMT_AUTO;
138     fnlen = strlen(cp);
139     upd->filename = (char *)malloc(fnlen + 1);
140   } else {
141     fnlen = p - cp;
142     upd->filename = (char *)malloc(fnlen +1);
143     c = *++p;
144     if (c && p[1])
145       /* More than one char - force failure below. */
146       c = '?';
147     switch (c) {
148       case 'a': upd->format = FMT_AUTO; break;
149       case 's': upd->format = FMT_SREC; break;
150       case 'i': upd->format = FMT_IHEX; break;
151       case 'r': upd->format = FMT_RBIN; break;
152       case 'e': upd->format = FMT_ELF; break;
153       case 'm': upd->format = FMT_IMM; break;
154       case 'b': upd->format = FMT_BIN; break;
155       case 'd': upd->format = FMT_DEC; break;
156       case 'h': upd->format = FMT_HEX; break;
157       case 'o': upd->format = FMT_OCT; break;
158       default:
159         avrdude_message(MSG_INFO, "%s: invalid file format '%s' in update specifier\n",
160                 progname, p);
161         free(upd->memtype);
162         free(upd);
163         return NULL;
164     }
165   }
166 
167   if (upd->filename == NULL) {
168     avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
169     free(upd->memtype);
170     free(upd);
171     return NULL;
172   }
173   memcpy(upd->filename, cp, fnlen);
174   upd->filename[fnlen] = 0;
175 
176   return upd;
177 }
178 
dup_update(UPDATE * upd)179 UPDATE * dup_update(UPDATE * upd)
180 {
181   UPDATE * u;
182 
183   u = (UPDATE *)malloc(sizeof(UPDATE));
184   if (u == NULL) {
185     // avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
186     // exit(1);
187     avrdude_oom("dup_update: out of memory\n");
188   }
189 
190   memcpy(u, upd, sizeof(UPDATE));
191 
192   if (upd->memtype != NULL)
193     u->memtype = strdup(upd->memtype);
194   else
195     u->memtype = NULL;
196   u->filename = strdup(upd->filename);
197 
198   return u;
199 }
200 
new_update(int op,char * memtype,int filefmt,char * filename,unsigned section)201 UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, unsigned section)
202 {
203   UPDATE * u;
204 
205   u = (UPDATE *)malloc(sizeof(UPDATE));
206   if (u == NULL) {
207     // avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
208     // exit(1);
209     avrdude_oom("new_update: out of memory\n");
210   }
211 
212   u->memtype = strdup(memtype);
213   u->filename = strdup(filename);
214   u->op = op;
215   u->format = filefmt;
216   u->section = section;
217 
218   return u;
219 }
220 
free_update(UPDATE * u)221 void free_update(UPDATE * u)
222 {
223     if (u != NULL) {
224 	if(u->memtype != NULL) {
225 	    free(u->memtype);
226 	    u->memtype = NULL;
227 	}
228 	if(u->filename != NULL) {
229 	    free(u->filename);
230 	    u->filename = NULL;
231 	}
232 	free(u);
233     }
234 }
235 
236 
do_op(PROGRAMMER * pgm,struct avrpart * p,UPDATE * upd,enum updateflags flags)237 int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags)
238 {
239   struct avrpart * v;
240   AVRMEM * mem;
241   int size, vsize;
242   int rc;
243 
244   mem = avr_locate_mem(p, upd->memtype);
245   if (mem == NULL) {
246     avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
247             upd->memtype, p->desc);
248     return -1;
249   }
250 
251   if (upd->op == DEVICE_READ) {
252     /*
253      * read out the specified device memory and write it to a file
254      */
255     if (quell_progress < 2) {
256       avrdude_message(MSG_INFO, "%s: reading %s memory:\n",
257             progname, mem->desc);
258 	  }
259     report_progress(0,1,"Reading");
260     rc = avr_read(pgm, p, upd->memtype, 0);
261     if (rc < 0) {
262       avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
263               progname, mem->desc, rc);
264       return -1;
265     }
266     report_progress(1,1,NULL);
267     size = rc;
268 
269     if (quell_progress < 2) {
270       if (rc == 0)
271         avrdude_message(MSG_INFO, "%s: Flash is empty, resulting file has no contents.\n",
272                         progname);
273       avrdude_message(MSG_INFO, "%s: writing output file \"%s\"\n",
274                       progname,
275                       strcmp(upd->filename, "-")==0 ? "<stdout>" : upd->filename);
276     }
277     rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size, 0);
278     if (rc < 0) {
279       avrdude_message(MSG_INFO, "%s: write to file '%s' failed\n",
280               progname, upd->filename);
281       return -1;
282     }
283   }
284   else if (upd->op == DEVICE_WRITE) {
285     /*
286      * write the selected device memory using data from a file; first
287      * read the data from the specified file
288      */
289     if (quell_progress < 2) {
290       avrdude_message(MSG_INFO, "%s: reading input file \"%s\"\n",
291                       progname,
292                       strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
293     }
294     rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
295     if (rc < 0) {
296       avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
297               progname, upd->filename);
298       return -1;
299     }
300     size = rc;
301 
302     /*
303      * write the buffer contents to the selected memory type
304      */
305     if (quell_progress < 2) {
306       avrdude_message(MSG_INFO, "%s: writing %s (%d bytes):\n",
307             progname, mem->desc, size);
308 	  }
309 
310 	//Prusa3D bootloader progress on lcd
311 	if (strcmp(pgm->type, "Wiring") == 0)
312 	{
313 		if (pgm->set_upload_size != 0)
314 			pgm->set_upload_size(pgm, size);
315 	}
316 
317     if (!(flags & UF_NOWRITE)) {
318       report_progress(0,1,"Writing");
319       rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
320       report_progress(1,1,NULL);
321     }
322     else {
323       // /*
324       //  * test mode, don't actually write to the chip, output the buffer
325       //  * to stdout in intel hex instead
326       //  */
327       // rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size, 0);
328     }
329 
330     if (rc < 0) {
331       avrdude_message(MSG_INFO, "%s: failed to write %s memory, rc=%d\n",
332               progname, mem->desc, rc);
333       return -1;
334     }
335 
336     vsize = rc;
337 
338     if (quell_progress < 2) {
339       avrdude_message(MSG_INFO, "%s: %d bytes of %s written\n", progname,
340             vsize, mem->desc);
341     }
342 
343   }
344   else if (upd->op == DEVICE_VERIFY) {
345     /*
346      * verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM])
347      * is the same as what is on the chip
348      */
349     pgm->vfy_led(pgm, ON);
350 
351     if (quell_progress < 2) {
352       avrdude_message(MSG_INFO, "%s: verifying %s memory against %s:\n",
353             progname, mem->desc, upd->filename);
354 
355       avrdude_message(MSG_INFO, "%s: load data %s data from input file %s:\n",
356             progname, mem->desc, upd->filename);
357     }
358 
359     rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
360     if (rc < 0) {
361       avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
362               progname, upd->filename);
363       return -1;
364     }
365     v = avr_dup_part(p);
366     size = rc;
367     if (quell_progress < 2) {
368       avrdude_message(MSG_INFO, "%s: input file %s contains %d bytes\n",
369             progname, upd->filename, size);
370       avrdude_message(MSG_INFO, "%s: reading on-chip %s data:\n",
371             progname, mem->desc);
372     }
373 
374     report_progress (0,1,"Reading");
375     rc = avr_read(pgm, p, upd->memtype, v);
376     if (rc < 0) {
377       avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
378               progname, mem->desc, rc);
379       pgm->err_led(pgm, ON);
380       return -1;
381     }
382     report_progress (1,1,NULL);
383 
384 
385 
386     if (quell_progress < 2) {
387       avrdude_message(MSG_INFO, "%s: verifying ...\n", progname);
388     }
389     rc = avr_verify(p, v, upd->memtype, size);
390     if (rc < 0) {
391       avrdude_message(MSG_INFO, "%s: verification error; content mismatch\n",
392               progname);
393       pgm->err_led(pgm, ON);
394       return -1;
395     }
396 
397     if (quell_progress < 2) {
398       avrdude_message(MSG_INFO, "%s: %d bytes of %s verified\n",
399               progname, rc, mem->desc);
400     }
401 
402     pgm->vfy_led(pgm, OFF);
403   }
404   else {
405     avrdude_message(MSG_INFO, "%s: invalid update operation (%d) requested\n",
406             progname, upd->op);
407     return -1;
408   }
409 
410   return 0;
411 }
412 
413