FreeCalypso > hg > fc-usbser-tools
comparison cp2102/intel_hex_in.c @ 55:c0084bf153e5
cp2102: Intel HEX reading implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 11 Sep 2023 19:45:56 +0000 |
parents | |
children | 842cff427588 |
comparison
equal
deleted
inserted
replaced
54:10789bcf07c4 | 55:c0084bf153e5 |
---|---|
1 /* | |
2 * This module implements a function for reading CP2102 EEPROM images | |
3 * in the Intel HEX format which we've copied from cp210x-program-1.0, | |
4 * the Python-language tool from 2014. | |
5 */ | |
6 | |
7 #include <sys/types.h> | |
8 #include <ctype.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include "cp210x_defs.h" | |
14 | |
15 extern u_char eeprom[SIZE_EEPROM]; | |
16 | |
17 static int | |
18 decode_hex_digit(c) | |
19 { | |
20 if (c >= '0' && c <= '9') | |
21 return(c - '0'); | |
22 if (c >= 'A' && c <= 'F') | |
23 return(c - 'A' + 10); | |
24 if (c >= 'a' && c <= 'f') | |
25 return(c - 'a' + 10); | |
26 return(-1); | |
27 } | |
28 | |
29 static int | |
30 decode_hex_byte(str) | |
31 char *str; | |
32 { | |
33 int u, l; | |
34 | |
35 u = decode_hex_digit(str[0]); | |
36 l = decode_hex_digit(str[1]); | |
37 return (u << 4) | l; | |
38 } | |
39 | |
40 void | |
41 read_intel_hex(filename) | |
42 char *filename; | |
43 { | |
44 FILE *inf; | |
45 char linebuf[1024], *cp; | |
46 int lineno; | |
47 unsigned eeprom_offset; | |
48 unsigned payload_len, record_len, n; | |
49 u_char record[21], csum; | |
50 unsigned record_addr, expect_addr; | |
51 | |
52 inf = fopen(filename, "r"); | |
53 if (!inf) { | |
54 perror(filename); | |
55 exit(1); | |
56 } | |
57 eeprom_offset = 0; | |
58 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { | |
59 if (!index(linebuf, '\n')) { | |
60 fprintf(stderr, | |
61 "%s line %d: too long or missing newline\n", | |
62 filename, lineno); | |
63 exit(1); | |
64 } | |
65 if (linebuf[0] != ':') | |
66 continue; | |
67 if (!isxdigit(linebuf[1]) || !isxdigit(linebuf[2])) { | |
68 inv_record: fprintf(stderr, | |
69 "%s line %d: invalid Intex HEX record\n", | |
70 filename, lineno); | |
71 exit(1); | |
72 } | |
73 payload_len = decode_hex_byte(linebuf + 1); | |
74 if (payload_len > 16) { | |
75 bad_payload_len: fprintf(stderr, | |
76 "%s line %d: unsupported payload length\n", | |
77 filename, lineno); | |
78 exit(1); | |
79 } | |
80 record_len = payload_len + 5; | |
81 cp = linebuf + 1; | |
82 csum = 0; | |
83 for (n = 0; n < payload_len; n++) { | |
84 if (!isxdigit(cp[0]) || !isxdigit(cp[1])) | |
85 goto inv_record; | |
86 record[n] = decode_hex_byte(cp); | |
87 cp += 2; | |
88 csum += record[n]; | |
89 } | |
90 if (csum) { | |
91 fprintf(stderr, | |
92 "%s line %d: bad Intel HEX record checksum\n", | |
93 filename, lineno); | |
94 exit(1); | |
95 } | |
96 if (record[3] == 0x00) { | |
97 if (payload_len != 16) | |
98 goto bad_payload_len; | |
99 if (eeprom_offset >= SIZE_EEPROM) { | |
100 fprintf(stderr, | |
101 "%s line %d: data continues past valid EEPROM size\n", | |
102 filename, lineno); | |
103 exit(1); | |
104 } | |
105 record_addr = (record[1] << 8) | record[2]; | |
106 expect_addr = EEPROM_START_ADDR + eeprom_offset; | |
107 if (record_addr != expect_addr) { | |
108 fprintf(stderr, | |
109 "%s line %d: record addr is %04X, but we expect %04X\n", | |
110 filename, lineno, record_addr, | |
111 expect_addr); | |
112 exit(1); | |
113 } | |
114 bcopy(record + 4, eeprom + eeprom_offset, 16); | |
115 eeprom_offset += 16; | |
116 } else if (record[3] == 0x01) { | |
117 if (payload_len) { | |
118 fprintf(stderr, | |
119 "%s line %d: nonzero payload length in end-marker record\n", | |
120 filename, lineno); | |
121 exit(1); | |
122 } | |
123 if (eeprom_offset < SIZE_EEPROM) { | |
124 fprintf(stderr, | |
125 "%s line %d: end-marker without full data\n", | |
126 filename, lineno); | |
127 exit(1); | |
128 } | |
129 break; | |
130 } else { | |
131 fprintf(stderr, | |
132 "%s line %d: unsupported Intel HEX record type\n", | |
133 filename, lineno); | |
134 exit(1); | |
135 } | |
136 } | |
137 fclose(inf); | |
138 if (!eeprom_offset) { | |
139 fprintf(stderr, "error: no Intel HEX EEPROM data found in %s\n", | |
140 filename); | |
141 exit(1); | |
142 } | |
143 if (eeprom_offset < SIZE_EEPROM) { | |
144 fprintf(stderr, "error: %s contains truncated data\n", | |
145 filename); | |
146 exit(1); | |
147 } | |
148 } |