1 /*
2 * Copyright (C) 2005-2019 Darron Broad
3 * All rights reserved.
4 *
5 * This file is part of Pickle Microchip PIC ICSP.
6 *
7 * Pickle Microchip PIC ICSP is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation.
10 *
11 * Pickle Microchip PIC ICSP is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with Pickle Microchip PIC ICSP. If not, see http://www.gnu.org/licenses/
18 */
19
20 #include "pickle.h"
21
22 /*
23 * SESSION
24 */
25 extern struct pickle p;
26
27 /*
28 * DETERMINE ARCH
29 *
30 * 12 | 14 | 14 new | 16 | 16 new | 24 | 32
31 */
32 uint32_t
pic_arch(const char * execname)33 pic_arch(const char *execname)
34 {
35 #ifdef P12
36 if (strcmp(execname, "p12") == 0)
37 return pic12_arch(); /* 12-bit word PIC10F/PIC12F/PIC16F */
38 #endif
39 #ifdef P14
40 if (strcmp(execname, "p14") == 0)
41 return pic14_arch(); /* 14-bit word PIC10F/PIC12F/PIC16F */
42 #endif
43 #ifdef N14
44 if (strcmp(execname, "n14") == 0)
45 return pic14n_arch(); /* 14-bit word PIC16F */
46 #endif
47 #ifdef P16
48 if (strcmp(execname, "p16") == 0)
49 return pic16_arch(); /* 16-bit word PIC18F */
50 #endif
51 #ifdef N16
52 if (strcmp(execname, "n16") == 0)
53 return pic16n_arch(); /* 16-bit word PIC18F */
54 #endif
55 #ifdef P24
56 if (strcmp(execname, "p24") == 0)
57 return pic24_arch(); /* 24-bit word PIC24/dsPIC */
58 #endif
59 #ifdef P32
60 if (strcmp(execname, "p32") == 0)
61 return pic32_arch(); /* 32-bit word PIC32 */
62 #endif
63 return 0; /* Unsupported */
64 }
65
66 /*
67 * COMPARE DEVICE NAMES FOR QSORT
68 */
69 int
pic_cmp(const void * p1,const void * p2)70 pic_cmp(const void *p1, const void *p2)
71 {
72 char *s1 = *(char **)p1, *s2 = *(char **)p2;
73
74 return strcasecmp(s1, s2);
75 }
76
77 /*
78 * DUMP DEVICE SELECTION
79 */
80 void
pic_selector(void)81 pic_selector(void)
82 {
83 if (p.pic->selector)
84 p.pic->selector();
85 else
86 printf("%s: information: unimplemented\n", __func__);
87 }
88
89 /*
90 * DUMP LOADER CONFIGURATION
91 */
92 void
pic_bootloader(void)93 pic_bootloader(void)
94 {
95 if (p.pic->bootloader)
96 p.pic->bootloader();
97 else
98 printf("%s: information: unimplemented\n", __func__);
99 }
100
101 /*
102 * BEGIN PROGRAMMING
103 */
104 void
pic_program_begin(void)105 pic_program_begin(void)
106 {
107 if (p.pic->program_begin)
108 p.pic->program_begin();
109 }
110
111 /*
112 * PROGRAM DATA
113 */
114 uint32_t
pic_program_data(uint32_t current_region,pic_data * pdata)115 pic_program_data(uint32_t current_region, pic_data *pdata)
116 {
117 if (p.pic->program_data)
118 return p.pic->program_data(current_region, pdata);
119
120 return PIC_REGIONNOTSUP;
121 }
122
123 /*
124 * END PROGRAMMING
125 */
pic_program_end(int config)126 void pic_program_end(int config)
127 {
128 if (p.pic->program_end)
129 p.pic->program_end(config);
130 }
131
132 /*
133 * BEGIN VERIFY
134 */
135 void
pic_verify_begin(void)136 pic_verify_begin(void)
137 {
138 if (p.pic->verify_begin)
139 p.pic->verify_begin();
140 }
141
142 /*
143 * VERIFY DATA
144 */
145 uint32_t
pic_verify_data(uint32_t current_region,pic_data * pdata,uint32_t * fail)146 pic_verify_data(uint32_t current_region, pic_data *pdata, uint32_t *fail)
147 {
148 if (p.pic->verify_data)
149 return p.pic->verify_data(current_region, pdata, fail);
150
151 return PIC_REGIONNOTSUP;
152 }
153
154 /*
155 * END VERIFY
156 */
pic_verify_end(void)157 void pic_verify_end(void)
158 {
159 if (p.pic->verify_end)
160 p.pic->verify_end();
161 }
162
163 #ifdef P32
164 /*
165 * READ PE FILE
166 *
167 * RETURNS BYTE POINTER OR NULL ON ERROR.
168 *
169 * WILL ADJUST FILE NAME WHEN ATTEMPTING TO CREATE CACHED HEX FILE (BIN)
170 */
171 uint8_t *
pic_pe_read_file(char * filename,uint32_t * nbytes)172 pic_pe_read_file(char *filename, uint32_t *nbytes)
173 {
174 int rc;
175 struct stat st;
176 uint8_t *pe;
177 FILE *fp;
178 char *s;
179
180 if (strstr(filename, ".bin")) {
181 rc = stat(filename, &st);
182 if (rc < 0) {
183 printf("%s: error: stat failed [%s]\n", __func__, filename);
184 return NULL;
185 }
186 *nbytes = st.st_size;
187 pe = (uint8_t *)calloc(*nbytes, sizeof(uint8_t));
188 if (pe == NULL) {
189 printf("%s: fatal error: calloc failed\n", __func__);
190 io_exit(EX_OSERR); /* Panic */
191 }
192 fp = fopen(filename, "rb");
193 if (fp == NULL) {
194 printf("%s: error: fopen failed [%s]\n", __func__, filename);
195 return NULL;
196 }
197 rc = fread((void *)pe, 1, *nbytes, fp);
198 if (rc != *nbytes) {
199 printf("%s: error: fread failed [%s]\n", __func__, filename);
200 return NULL;
201 }
202 fclose(fp);
203 } else { /* .hex */
204 s = strstr(filename, ".hex");
205 if (s == NULL) {
206 return NULL;
207 }
208 *nbytes = inhx32_memory_create(&pe, filename);
209 if (*nbytes == 0) {
210 return NULL;
211 }
212 strcpy(s, ".bin");
213 fp = fopen(filename, "wb");
214 if (fp != NULL) {
215 rc = fwrite((void *)pe, 1, *nbytes, fp);
216 fclose(fp);
217 if (rc != *nbytes)
218 unlink(filename);
219 }
220 }
221 return pe;
222 }
223
224 /*
225 * LOOK UP PE FILE NAME
226 */
227 int
pic_pe_lookup_file(char * pathname,const char * filename)228 pic_pe_lookup_file(char *pathname, const char *filename)
229 {
230 int rc;
231
232 if (p.etc[0]) {
233 rc = snprintf(pathname, STRLEN, "%s/%s", p.etc, filename);
234 if (rc < 0) {
235 printf("%s: fatal error: snprintf failed\n", __func__);
236 io_exit(EX_OSERR); /* Panic */
237 } else if (rc >= STRLEN) {
238 printf("%s: fatal error: snprintf overrun\n", __func__);
239 io_exit(EX_SOFTWARE); /* Panic */
240 }
241
242 if (access(pathname, R_OK) == 0)
243 return 0;
244 }
245
246 char *dotdup = (char *)strdup(p.dotfile);
247 if (dotdup == NULL) {
248 printf("%s: fatal error: strdup failed\n", __func__);
249 io_exit(EX_OSERR); /* Panic */
250 }
251
252 char *dname = dirname(dotdup);
253
254 rc = snprintf(pathname, STRLEN, "%s/%s", dname, filename);
255 if (rc < 0) {
256 printf("%s: fatal error: snprintf failed\n", __func__);
257 io_exit(EX_OSERR); /* Panic */
258 } else if (rc >= STRLEN) {
259 printf("%s: fatal error: snprintf overrun\n", __func__);
260 io_exit(EX_SOFTWARE); /* Panic */
261 }
262
263 free(dotdup);
264 if (access(pathname, R_OK) == 0)
265 return 0;
266
267 bzero(pathname, STRLEN);
268 return -1;
269 }
270
271 /*
272 * LOOK UP PE FILE .BIN OR .HEX
273 *
274 * FILE IS PE FILENAME WITHOUT FILE NAME EXTENSION
275 */
276 int
pic_pe_lookup(char * pathname,const char * file)277 pic_pe_lookup(char *pathname, const char *file)
278 {
279 char filename[STRLEN];
280 int rc;
281
282 rc = snprintf(filename, STRLEN, "%s.bin", file);
283 if (rc < 0) {
284 printf("%s: fatal error: snprintf failed\n", __func__);
285 io_exit(EX_OSERR); /* Panic */
286 } else if (rc >= STRLEN) {
287 printf("%s: fatal error: snprintf overrun\n", __func__);
288 io_exit(EX_SOFTWARE); /* Panic */
289 }
290
291 if (pic_pe_lookup_file(pathname, filename) == 0)
292 return 0;
293
294 rc = snprintf(filename, STRLEN, "%s.hex", file);
295 if (rc < 0) {
296 printf("%s: fatal error: snprintf failed\n", __func__);
297 io_exit(EX_OSERR); /* Panic */
298 } else if (rc >= STRLEN) {
299 printf("%s: fatal error: snprintf overrun\n", __func__);
300 io_exit(EX_SOFTWARE); /* Panic */
301 }
302
303 return pic_pe_lookup_file(pathname, filename);
304 }
305 #endif /* P32 */
306
307 /*
308 * READ CONFIG
309 *
310 * Return -1 on error, 0 OK
311 */
312 int
pic_read_config(void)313 pic_read_config(void)
314 {
315 if (p.pic->read_config_memory)
316 return p.pic->read_config_memory();
317
318 printf("%s: information: unimplemented\n", __func__);
319
320 return -1;
321 }
322
323 /*
324 * DETERMINE PROGRAM PARTITION COUNT
325 *
326 * INVOKE AFTER `pic_read_config'
327 */
328 uint32_t
pic_get_program_count(void)329 pic_get_program_count(void)
330 {
331 uint32_t count = 1;
332
333 if (p.pic->get_program_count)
334 count = p.pic->get_program_count();
335 else
336 printf("%s: information: unimplemented\n", __func__);
337
338 return count;
339 }
340
341 /*
342 * DETERMINE PROGRAM FLASH SIZE
343 *
344 * INVOKE AFTER `pic_read_config'
345 */
346 uint32_t
pic_get_program_size(uint32_t * addr,uint32_t partition)347 pic_get_program_size(uint32_t *addr, uint32_t partition)
348 {
349 uint32_t size = UINT32_MAX;
350
351 if (p.pic->get_program_size)
352 size = p.pic->get_program_size(addr, partition);
353 else
354 printf("%s: information: unimplemented\n", __func__);
355
356 return size;
357 }
358
359 /*
360 * DETERMINE DATA EEPROM/FLASH SIZE
361 *
362 * INVOKE AFTER `pic_read_config'
363 */
364 uint32_t
pic_get_data_size(uint32_t * addr)365 pic_get_data_size(uint32_t *addr)
366 {
367 uint32_t size = UINT32_MAX;
368
369 if (p.pic->get_data_size)
370 size = p.pic->get_data_size(addr);
371 else
372 printf("%s: information: unimplemented\n", __func__);
373
374 return size;
375 }
376
377 /*
378 * DETERMINE EXECUTIVE SIZE
379 *
380 * INVOKE AFTER `pic_read_config'
381 */
382 uint32_t
pic_get_executive_size(uint32_t * addr)383 pic_get_executive_size(uint32_t *addr)
384 {
385 uint32_t size = UINT32_MAX;
386
387 if (p.pic->get_executive_size)
388 size = p.pic->get_executive_size(addr);
389 else
390 printf("%s: information: unimplemented\n", __func__);
391
392 return size;
393 }
394
395 /*
396 * DETERMINE BOOT FLASH SIZE
397 *
398 * INVOKE AFTER `pic_read_config'
399 */
400 uint32_t
pic_get_boot_size(uint32_t * addr)401 pic_get_boot_size(uint32_t *addr)
402 {
403 uint32_t size = UINT32_MAX;
404
405 if (p.pic->get_boot_size)
406 size = p.pic->get_boot_size(addr);
407 else
408 printf("%s: information: unimplemented\n", __func__);
409
410 return size;
411 }
412
413 /*
414 * READ PROGRAM FLASH / DATA FLASH MEMORY BLOCK
415 *
416 * INVOKE AFTER `pic_get_program_size'
417 */
418 uint32_t
pic_read_program_memory_block(uint32_t * data,uint32_t addr,uint32_t size)419 pic_read_program_memory_block(uint32_t *data, uint32_t addr, uint32_t size)
420 {
421 uint32_t rc = UINT32_MAX;
422
423 if (p.pic->read_program_memory_block)
424 rc = p.pic->read_program_memory_block(data, addr, size);
425 else
426 printf("%s: information: unimplemented\n", __func__);
427
428 return rc;
429 }
430
431 /*
432 * READ DATA EEPROM/FLASH MEMORY BLOCK
433 *
434 * INVOKE AFTER `pic_get_data_size'
435 */
436 uint32_t
pic_read_data_memory_block(uint16_t * data,uint32_t addr,uint16_t size)437 pic_read_data_memory_block(uint16_t *data, uint32_t addr, uint16_t size)
438 {
439 uint32_t rc = UINT32_MAX;
440
441 if (p.pic->read_data_memory_block)
442 rc = p.pic->read_data_memory_block(data, addr, size);
443 else
444 printf("%s: information: unimplemented\n", __func__);
445
446 return rc;
447 }
448
449 /*
450 * BULK ERASE DEVICE
451 *
452 * INVOKE AFTER `pic_read_config'
453 */
454 void
pic_bulk_erase(void)455 pic_bulk_erase(void)
456 {
457 if (p.pic->bulk_erase) {
458 p.pic->bulk_erase();
459 } else
460 printf("%s: information: unimplemented\n", __func__);
461 }
462
463 /*
464 * PROGRAM FILE
465 */
466 void
pic_program(char * filename,int blank)467 pic_program(char *filename, int blank)
468 {
469 uint32_t count = 0, nbytes;
470 pic_data **pdata = NULL;
471 uint32_t current_region = PIC_REGIONNOTSUP;
472
473 if (!p.pic->program_data || !p.pic->program_end) {
474 printf("%s: information: program unimplemented\n", __func__);
475 return;
476 }
477 if (!p.pic->bulk_erase) {
478 printf("%s: information: erase unimplemented\n", __func__);
479 return;
480 }
481 if (pic_read_config() < 0)
482 return;
483
484 if (blank)
485 p.pic->bulk_erase();
486
487 nbytes = inhx32_array_create(&pdata, filename, &count);
488 if (nbytes == 0)
489 return;
490
491 if (p.pic->program_begin)
492 p.pic->program_begin();
493
494 for (uint32_t i = 0; i < count; ++i)
495 current_region = p.pic->program_data(current_region, pdata[i]);
496
497 p.pic->program_end(blank);
498
499 printf("Total: %u\n", nbytes);
500
501 inhx32_array_free(pdata, count);
502 }
503
504 /*
505 * VERIFY FILE
506 *
507 * RETURN 1 FOR FAULT OR NUMBER OF VERIFY ERRORS
508 */
509 uint32_t
pic_verify(char * filename)510 pic_verify(char *filename)
511 {
512 uint32_t count = 0, nbytes;
513 pic_data **pdata = NULL;
514 uint16_t current_region = PIC_REGIONNOTSUP;
515 uint32_t fail = 0;
516
517 if (!p.pic->verify_data || !p.pic->verify_end) {
518 printf("%s: information: verify unimplemented\n", __func__);
519 return 1;
520 }
521 if (pic_read_config() < 0)
522 return 1;
523
524 nbytes = inhx32_array_create(&pdata, filename, &count);
525 if (nbytes == 0)
526 return 0;
527
528 if (p.pic->verify_begin)
529 p.pic->verify_begin();
530
531 for (uint32_t i = 0; i < count; ++i)
532 current_region = p.pic->verify_data(current_region, pdata[i], &fail);
533
534 p.pic->verify_end();
535
536 printf("Total: %u Fail: %u\n", nbytes, fail);
537
538 inhx32_array_free(pdata, count);
539
540 return fail;
541 }
542
543 /*
544 * VIEW FILE
545 */
546 void
pic_view(char * filename,int raw)547 pic_view(char *filename, int raw)
548 {
549 uint32_t count = 0, nbytes;
550 pic_data **pdata = NULL;
551
552 if (!p.pic->view_data) {
553 printf("%s: information: view unimplemented\n", __func__);
554 return;
555 }
556
557 nbytes = inhx32_array_create(&pdata, filename, &count);
558 if (nbytes == 0)
559 return;
560
561 if (!raw) {
562 for (uint32_t i = 0; i < count; ++i)
563 p.pic->view_data(pdata[i]);
564
565 printf("Total: %u\n", nbytes);
566 } else {
567 for (uint32_t i = 0; i < count; ++i) {
568 for (uint32_t j = 0; j < pdata[i]->nbytes; ++j)
569 printf("%02X ", pdata[i]->bytes[j]);
570
571 printf("\n");
572 }
573 }
574
575 inhx32_array_free(pdata, count);
576 }
577
578 /*
579 * WRITE BANDGAP CONFIG
580 */
581 void
pic_writebandgap(uint16_t bandgap)582 pic_writebandgap(uint16_t bandgap)
583 {
584 if (p.pic->write_bandgap) {
585 if (!pic_read_config())
586 p.pic->write_bandgap(bandgap);
587 } else
588 printf("%s: information: BANDGAP is not supported on this architecture\n", __func__);
589 }
590
591 /*
592 * WRITE OSCILLATOR CALIBRATION
593 */
594 void
pic_writeosccal(uint16_t osccal)595 pic_writeosccal(uint16_t osccal)
596 {
597 if (p.pic->write_osccal) {
598 if (!pic_read_config())
599 p.pic->write_osccal(osccal);
600 } else
601 printf("%s: information: OSCCAL is not supported on this architecture\n", __func__);
602 }
603
604 /*
605 * BLANK DEVICE
606 */
607 void
pic_blank(int config)608 pic_blank(int config)
609 {
610 if (p.pic->bulk_erase) {
611 if (config && pic_read_config())
612 return;
613 p.pic->bulk_erase();
614 } else
615 printf("%s: information: unimplemented\n", __func__);
616 }
617
618 /*
619 * ERASE ROW(S)
620 */
621 void
pic_erase(uint32_t row,uint32_t nrows)622 pic_erase(uint32_t row, uint32_t nrows)
623 {
624 if (p.pic->row_erase) {
625 if (!pic_read_config())
626 p.pic->row_erase(row, nrows);
627 } else
628 printf("%s: information: unimplemented\n", __func__);
629 }
630
631 /*
632 * DUMP DEVICE ID
633 */
634 void
pic_dumpdeviceid(void)635 pic_dumpdeviceid(void)
636 {
637 if (p.pic->dumpdeviceid) {
638 if (!pic_read_config())
639 p.pic->dumpdeviceid();
640 } else
641 printf("%s: information: unimplemented\n", __func__);
642 }
643
644 /*
645 * DUMP CONFIGURATION
646 */
647 void
pic_dumpconfig(void)648 pic_dumpconfig(void)
649 {
650 if (p.pic->dumpconfig) {
651 if (!pic_read_config()) {
652 uint32_t count = pic_get_program_count();
653
654 for (uint32_t i = 0; i < count; ++i)
655 p.pic->dumpconfig(PIC_VERBOSE, i);
656 }
657 } else
658 printf("%s: information: unimplemented\n", __func__);
659 }
660
661 /*
662 * DUMP OSCILLATOR CALIBRATION
663 */
664 void
pic_dumposccal(void)665 pic_dumposccal(void)
666 {
667 if (p.pic->dumposccal) {
668 if (!pic_read_config())
669 p.pic->dumposccal();
670 } else
671 printf("%s: information: OSCCAL is not supported on this architecture\n", __func__);
672 }
673
674 /******************************************************************************
675 INHX32 DATA DUMP
676 *****************************************************************************/
677
678 /*
679 * DUMP EXTENDED ADDRESS
680 *
681 * :BBAAAATTHHHHCC
682 *
683 * BB 02 = NUMBER OF BYTES
684 * AAAA 0000 = ADDRESS (0000)
685 * TT 04 = EXTENDED_LINEAR_ADDRESS
686 * HHHH = EXTENDED ADDRESS << 16
687 * CC = CHECKSUM
688 *
689 * FLAG=1 UPDATE AND OUTPUT ALWAYS
690 * FLAG=0 UPDATE AND OUTPUT IF CHANGED
691 */
692 void
pic_dumpaddr(uint32_t addr,int flag)693 pic_dumpaddr(uint32_t addr, int flag)
694 {
695 static uint16_t oldaddr = 0;
696 uint16_t newaddr = addr >> 16;
697
698 if (flag || (newaddr != oldaddr)) {
699 uint8_t hb = newaddr >> 8;
700 uint8_t lb = newaddr & 0xFF;
701 uint8_t cc = 0x100 - 0x06 - hb - lb;
702 printf(":02000004%02X%02X%02X\n", hb, lb, cc);
703 }
704 oldaddr = newaddr;
705 }
706
707 /*
708 * DUMP 8-BIT BYTE AS INHX32 DATA
709 */
710 void
pic_dumpbyte(uint32_t addr,uint8_t byte)711 pic_dumpbyte(uint32_t addr, uint8_t byte)
712 {
713 uint8_t cc, hb, lb;
714 hb = addr >> 8;
715 lb = addr;
716 printf(":01%02X%02X00", hb, lb);
717 cc = 0x01 + hb + lb + 0x00;
718 lb = byte;
719 cc = cc + lb;
720 printf("%02X%02X\n", lb, (0x100 - cc) & 0xFF);
721 }
722
723 /*
724 * DUMP 16-BIT WORD AS INHX32 DATA
725 */
726 void
pic_dumpword16(uint32_t addr,uint16_t word)727 pic_dumpword16(uint32_t addr, uint16_t word)
728 {
729 uint8_t cc, hb, lb;
730 hb = addr >> 7;
731 lb = addr << 1;
732 printf(":02%02X%02X00", hb, lb);
733 cc = 0x02 + hb + lb + 0x00;
734 hb = word >> 8;
735 lb = word;
736 cc = cc + hb + lb;
737 printf("%02X%02X%02X\n", lb, hb, (0x100 - cc) & 0xFF);
738 }
739
740 /*
741 * DUMP 32-BIT WORD AS INHX32 DATA
742 */
743 void
pic_dumpword32(uint32_t addr,uint32_t word)744 pic_dumpword32(uint32_t addr, uint32_t word)
745 {
746 uint8_t cc, b3, b2, b1, b0;
747 b1 = addr >> 7;
748 b0 = addr << 1;
749 printf(":04%02X%02X00", b1, b0);
750 cc = 0x04 + b1 + b0 + 0x00;
751 b3 = word >> 24;
752 b2 = word >> 16;
753 b1 = word >> 8;
754 b0 = word;
755 cc = cc + b3 + b2 + b1 + b0;
756 printf("%02X%02X%02X%02X%02X\n", b0, b1, b2, b3, (0x0100 - cc) & 0xFF);
757 }
758
759 /*
760 * DUMP DEVICE AS INHX32 DATA
761 */
762 void
pic_dumpdevice(void)763 pic_dumpdevice(void)
764 {
765 uint32_t addr, size, count;
766
767 /* Get userid/config */
768 if (pic_read_config() < 0)
769 return;
770
771 /* Program flash */
772 count = pic_get_program_count();
773 for (uint i = 0; i < count; ++i) {
774 /* Get program flash size */
775 size = pic_get_program_size(&addr, i);
776 if (size == UINT32_MAX) {
777 printf("%s: fatal error: program flash size invalid\n", __func__);
778 io_exit(EX_SOFTWARE); /* Panic */
779 }
780 /* Dump program flash */
781 if (size)
782 pic_dump_program(addr, size, PIC_INHX32);
783 }
784
785 /* Boot flash */
786 if (p.pic->get_boot_size) {
787 /* Get boot flash size */
788 size = pic_get_boot_size(&addr);
789 if (size == UINT32_MAX) {
790 printf("%s: fatal error: program flash size invalid\n", __func__);
791 io_exit(EX_SOFTWARE); /* Panic */
792 }
793 /* Dump boot flash */
794 if (size)
795 pic_dump_program(addr, size, PIC_INHX32);
796 }
797
798 /* Data EEPROM/flash */
799 if (p.pic->get_data_size) {
800 /* Get data EEPROM/flash size */
801 size = pic_get_data_size(&addr);
802 if (size == UINT32_MAX) {
803 printf("%s: fatal error: data EEPROM/flash size invalid\n", __func__);
804 io_exit(EX_SOFTWARE); /* Panic */
805 }
806 /* Dump data EEPROM/flash */
807 if (size)
808 pic_dump_data(addr, size, PIC_INHX32);
809 }
810
811 /* Userid/Config */
812 if (p.pic->dumpdevice) {
813 p.pic->dumpdevice();
814 }
815
816 /* EOF */
817 printf(":00000001FF\n");
818 }
819
820 /******************************************************************************
821 HEXADECIMAL DATA DUMP
822 *****************************************************************************/
823
824 /*
825 * DUMP ADDRESS/SIZE ADJUST
826 */
827 int
pic_dumpadj(uint32_t * baddr,uint32_t * bsize,uint32_t naddr,uint32_t nwords)828 pic_dumpadj(uint32_t *baddr, uint32_t *bsize, uint32_t naddr, uint32_t nwords)
829 {
830 if (naddr != UINT32_MAX) {
831 uint32_t laddr = *baddr + (*bsize * p.pic->dumpadj);
832 if (naddr >= *baddr && naddr < laddr) {
833 *bsize -= (naddr - *baddr) / p.pic->dumpadj;
834 *baddr = naddr;
835 } else if (naddr != *baddr) {
836 printf("%s: information: address invalid\n", __func__);
837 return -1;
838 }
839 }
840 if (nwords != UINT32_MAX) {
841 if (nwords < *bsize)
842 *bsize = nwords;
843 }
844 return 0;
845 }
846
847 /*
848 * DUMP PROGRAM FLASH IN HEX
849 */
850 void
pic_dumpprogram(uint32_t a,uint32_t n)851 pic_dumpprogram(uint32_t a, uint32_t n)
852 {
853 uint32_t addr, size, count;
854
855 if (pic_read_config() < 0)
856 return;
857
858 count = pic_get_program_count();
859 for (uint32_t i = 0; i < count; ++i) {
860 /* Get program flash size */
861 size = pic_get_program_size(&addr, i);
862 if (size == UINT32_MAX) {
863 printf("%s: fatal error: program flash size invalid\n", __func__);
864 io_exit(EX_SOFTWARE); /* Panic */
865 }
866 if (size == 0) {
867 printf("%s: information: program flash is not supported on this device\n", __func__);
868 return;
869 }
870 /* Adjust address and size */
871 if (pic_dumpadj(&addr, &size, a, n))
872 return;
873 /* Dump program flash */
874 pic_dump_program(addr, size, PIC_HEXDEC);
875 }
876 }
877
878 /*
879 * DUMP DATA EEPROM/FLASH IN HEX
880 */
881 void
pic_dumpdata(void)882 pic_dumpdata(void)
883 {
884 uint32_t addr, size;
885
886 if (!p.pic->get_data_size) {
887 printf("%s: information: data EEPROM/flash is not supported on this architecture\n", __func__);
888 return;
889 }
890
891 if (pic_read_config() < 0)
892 return;
893
894 /* Get data EEPROM/data flash size */
895 size = pic_get_data_size(&addr);
896 if (size == UINT32_MAX) {
897 printf("%s: fatal error: data EEPROM/flash size invalid\n", __func__);
898 io_exit(EX_SOFTWARE); /* Panic */
899 }
900 if (size == 0) {
901 printf("%s: information: data EEPROM/flash is not supported on this device\n", __func__);
902 return;
903 }
904 /* Dump data EEPROM/flash */
905 pic_dump_data(addr, size, PIC_HEXDEC);
906 }
907
908 /*
909 * DUMP EXECUTIVE FLASH IN HEX
910 */
911 void
pic_dumpexec(uint32_t a,uint32_t n)912 pic_dumpexec(uint32_t a, uint32_t n)
913 {
914 uint32_t addr, size;
915
916 if (!p.pic->get_executive_size) {
917 printf("%s: information: EXECUTIVE flash is not supported on this architecture\n", __func__);
918 return;
919 }
920
921 if (pic_read_config() < 0)
922 return;
923
924 /* Get program executive size */
925 size = pic_get_executive_size(&addr);
926 if (size == UINT32_MAX) {
927 printf("%s: fatal error: EXECUTIVE flash size invalid\n", __func__);
928 io_exit(EX_SOFTWARE); /* Panic */
929 }
930 if (size == 0) {
931 printf("%s: information: EXECUTIVE flash is not supported on this device\n", __func__);
932 return;
933 }
934 /* Adjust address and size */
935 if (pic_dumpadj(&addr, &size, a, n))
936 return;
937 /* Dump program executive */
938 pic_dump_program(addr, size, PIC_HEXDEC);
939 }
940
941 /*
942 * DUMP BOOT FLASH IN HEX
943 */
944 void
pic_dumpboot(uint32_t a,uint32_t n)945 pic_dumpboot(uint32_t a, uint32_t n)
946 {
947 uint32_t addr, size;
948
949 if (!p.pic->get_boot_size) {
950 printf("%s: information: BOOT flash is not supported on this architecture\n", __func__);
951 return;
952 }
953
954 if (pic_read_config() < 0)
955 return;
956
957 /* Get boot flash size */
958 size = pic_get_boot_size(&addr);
959 if (size == UINT32_MAX) {
960 printf("%s: fatal error: BOOT flash size invalid\n", __func__);
961 io_exit(EX_SOFTWARE); /* Panic */
962 }
963 if (size == 0) {
964 printf("%s: information: BOOT flash is not supported on this device\n", __func__);
965 return;
966 }
967 /* Adjust address and size */
968 if (pic_dumpadj(&addr, &size, a, n))
969 return;
970 /* Dump boot flash */
971 pic_dump_program(addr, size, PIC_HEXDEC);
972 }
973
974 /******************************************************************************
975 DUMP HEX / INHX32 PROGRAM AND DATA
976 *****************************************************************************/
977
978 /*
979 * DUMP PROGRAM FLASH
980 */
981 void
pic_dump_program(uint32_t addr,uint32_t size,int mode)982 pic_dump_program(uint32_t addr, uint32_t size, int mode)
983 {
984 uint32_t data_size = sizeof(uint32_t) * (size + 16);
985
986 /* Allocate program array */
987 uint32_t *data = (uint32_t *)malloc(data_size);
988 if (data == NULL) {
989 printf("%s: fatal error: malloc failed\n", __func__);
990 io_exit(EX_OSERR); /* Panic */
991 }
992 memset((void *)data, -1, data_size);
993 /* Read program */
994 if (pic_read_program_memory_block(data, addr, size) == UINT32_MAX) {
995 printf("%s: fatal error: program flash read failed\n", __func__);
996 io_exit(EX_SOFTWARE); /* Panic */
997 }
998 /* Dump */
999 if (mode == PIC_HEXDEC) {
1000 pic_dumphexcode(addr, size, data);
1001 } else if (mode == PIC_INHX32) {
1002 pic_dumpinhxcode(addr, size, data);
1003 }
1004 free(data);
1005 }
1006
1007 /*
1008 * DETECT EMPTY PROGRAM FLASH ROW
1009 */
1010 int
pic_mtcode(uint32_t compar,uint32_t size,uint32_t * data)1011 pic_mtcode(uint32_t compar, uint32_t size, uint32_t *data)
1012 {
1013 uint32_t mtrow = 0;
1014
1015 for (uint32_t j = 0; j < size; ++j) {
1016 if (data[j] == compar)
1017 mtrow++;
1018 }
1019 return (mtrow == size);
1020 }
1021
1022 /*
1023 * DUMP HEX PROGRAM FLASH WORDS
1024 */
1025 void
pic_dumphexcode(uint32_t addr,uint32_t size,uint32_t * data)1026 pic_dumphexcode(uint32_t addr, uint32_t size, uint32_t *data)
1027 {
1028 if (p.pic->dumphexcode)
1029 p.pic->dumphexcode(addr, size, data);
1030 else
1031 printf("%s: information: unimplemented\n", __func__);
1032 }
1033
1034 /*
1035 * DUMP INHX32 PROGRAM FLASH WORDS
1036 */
1037 void
pic_dumpinhxcode(uint32_t addr,uint32_t size,uint32_t * data)1038 pic_dumpinhxcode(uint32_t addr, uint32_t size, uint32_t *data)
1039 {
1040 if (p.pic->dumpinhxcode)
1041 p.pic->dumpinhxcode(addr, size, data);
1042 else
1043 printf("%s: information: unimplemented\n", __func__);
1044 }
1045
1046 /*
1047 * DUMP DATA EEPROM/FLASH
1048 */
1049 void
pic_dump_data(uint32_t addr,uint32_t size,int mode)1050 pic_dump_data(uint32_t addr, uint32_t size, int mode)
1051 {
1052 uint32_t data_size = sizeof(uint16_t) * (size + 16);
1053
1054 /* Allocate data EEPROM/flash array */
1055 uint16_t *data = (uint16_t *)malloc(data_size);
1056 if (data == NULL) {
1057 printf("%s: fatal error: malloc failed\n", __func__);
1058 io_exit(EX_OSERR); /* Panic */
1059 }
1060 memset((void *)data, -1, data_size);
1061 /* Read data EEPROM/flash */
1062 if (pic_read_data_memory_block(data, addr, size) == UINT32_MAX) {
1063 printf("%s: fatal error: data EEPROM/flash read failed\n", __func__);
1064 io_exit(EX_SOFTWARE); /* Panic */
1065 }
1066 /* Dump */
1067 if (mode == PIC_HEXDEC) {
1068 pic_dumphexdata(addr, size, data);
1069 } else if (mode == PIC_INHX32) {
1070 pic_dumpinhxdata(addr, size, data);
1071 }
1072 free(data);
1073 }
1074
1075 /*
1076 * DETECT EMPTY DATA EEPROM/FLASH ROW
1077 */
1078 int
pic_mtdata(uint16_t compar,uint32_t size,uint16_t * data)1079 pic_mtdata(uint16_t compar, uint32_t size, uint16_t *data)
1080 {
1081 uint32_t mtrow = 0;
1082
1083 for (uint32_t j = 0; j < size; ++j) {
1084 if (data[j] == compar)
1085 mtrow++;
1086 }
1087 return (mtrow == size);
1088 }
1089
1090 /*
1091 * DUMP HEX DATA EEPROM/FLASH BYTES/WORDS
1092 */
1093 void
pic_dumphexdata(uint32_t addr,uint32_t size,uint16_t * data)1094 pic_dumphexdata(uint32_t addr, uint32_t size, uint16_t *data)
1095 {
1096 if (p.pic->dumphexdata)
1097 p.pic->dumphexdata(addr, size, data);
1098 else
1099 printf("%s: information: unimplemented\n", __func__);
1100 }
1101
1102 /*
1103 * DUMP INHX32 DATA EEPROM/FLASH BYTES/WORDS
1104 */
1105 void
pic_dumpinhxdata(uint32_t addr,uint32_t size,uint16_t * data)1106 pic_dumpinhxdata(uint32_t addr, uint32_t size, uint16_t *data)
1107 {
1108 if (p.pic->dumpinhxdata)
1109 p.pic->dumpinhxdata(addr, size, data);
1110 else
1111 printf("%s: information: unimplemented\n", __func__);
1112 }
1113
1114 /******************************************************************************
1115 DEBUGGING
1116 *****************************************************************************/
1117
1118 void
pic_debug(void)1119 pic_debug(void)
1120 {
1121 if (!p.pic->debug) {
1122 printf("%s: information: unimplemented\n", __func__);
1123 return;
1124 }
1125
1126 if (pic_read_config() < 0)
1127 return;
1128
1129 p.pic->debug();
1130 }
1131
1132 /******************************************************************************
1133 PANEL WRITING
1134 *****************************************************************************/
1135
1136 /*
1137 * WRITE PANEL
1138 *
1139 * mode:
1140 * PIC_PANEL_BEGIN
1141 * data1: memory region
1142 * data2: memory size
1143 *
1144 * PIC_PANEL_UPDATE
1145 * data1: memory address
1146 * data2: memory data
1147 *
1148 * PIC_PANEL_END
1149 * data1: void
1150 * data2: void
1151 */
1152 void
pic_write_panel(int mode,uint32_t data1,uint32_t data2)1153 pic_write_panel(int mode, uint32_t data1, uint32_t data2)
1154 {
1155 static uint32_t write_pending = 0;
1156 static uint32_t panel_region = PIC_REGIONNOTSUP;
1157 static uint32_t panel_address = 0;
1158 static uint32_t *panel = NULL;
1159 static uint32_t panel_size = 0;
1160
1161 if (p.pic->write_panel == NULL) {
1162 printf("%s: fatal error: write panel unimplemented\n", __func__);
1163 io_exit(EX_SOFTWARE); /* Panic */
1164 }
1165 if (mode == PIC_PANEL_BEGIN || mode == PIC_PANEL_END) {
1166 if (panel) {
1167 if (write_pending) {
1168 write_pending = 0;
1169 p.pic->write_panel(panel_region, panel_address, panel, panel_size);
1170 }
1171 free(panel);
1172 panel_region = PIC_REGIONNOTSUP;
1173 panel_address = 0;
1174 panel = NULL;
1175 panel_size = 0;
1176 }
1177 }
1178 if (mode == PIC_PANEL_BEGIN) {
1179 panel_region = data1; /* MEMORY REGION */
1180 panel_size = data2; /* MEMORY SIZE */
1181 }
1182 if (mode == PIC_PANEL_BEGIN || mode == PIC_PANEL_UPDATE) {
1183 if (panel == NULL) {
1184 if (panel_size == 0) {
1185 printf("%s: fatal error: zero sized panel\n", __func__);
1186 io_exit(EX_SOFTWARE); /* Panic */
1187 }
1188 panel = malloc(sizeof(uint32_t) * panel_size);
1189 if (panel == NULL) {
1190 printf("%s: fatal error: malloc failed\n", __func__);
1191 io_exit(EX_SOFTWARE); /* Panic */
1192 }
1193 memset((void *)panel, -1, sizeof(uint32_t) * panel_size);
1194 }
1195 }
1196 if (mode == PIC_PANEL_UPDATE) {
1197 uint32_t address, new_address, boundary, mask;
1198
1199 boundary = 0 - panel_size;
1200 mask = panel_size - 1;
1201 address = data1; /* MEMORY ADDRESS */
1202 new_address = address & boundary;
1203 if (new_address != panel_address) {
1204 if (write_pending) {
1205 write_pending = 0;
1206 p.pic->write_panel(panel_region, panel_address, panel, panel_size);
1207 memset((void *)panel, -1, sizeof(uint32_t) * panel_size);
1208 }
1209 panel_address = new_address;
1210 }
1211 panel[address & mask] = data2; /* MEMORY DATA */
1212 write_pending++;
1213 }
1214 }
1215