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