comparison cp2102/apply_eeprom_patch.c @ 92:915a6fa7723e

cp2102-patch-ee-image program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 28 Sep 2023 01:37:43 +0000
parents
children
comparison
equal deleted inserted replaced
91:f4a7ac90cf39 92:915a6fa7723e
1 /*
2 * This function implemented in this module reads a CP2102 EEPROM patch
3 * specification file (which can also be a baud rate table file) and applies
4 * patches to the EEPROM image in RAM.
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 char cp2102_install_dir[] = "/opt/freecalypso/cp2102";
18
19 static void
20 apply_baud_entry(filename, lineno, args)
21 char *filename, *args;
22 {
23 unsigned entry_idx, intend_baud, baudgen_val, timeout_val;
24 unsigned prescaler, extra_byte;
25 char *cp = args;
26 u_char *eerec;
27
28 if (!isdigit(*cp)) {
29 inv: fprintf(stderr, "%s line %d: invalid syntax for baud-entry\n",
30 filename, lineno);
31 exit(1);
32 }
33 entry_idx = strtoul(cp, &cp, 10);
34 while (isspace(*cp))
35 cp++;
36 if (*cp++ != ':')
37 goto inv;
38 while (isspace(*cp))
39 cp++;
40 if (!isdigit(*cp))
41 goto inv;
42 intend_baud = strtoul(cp, &cp, 10);
43 while (isspace(*cp))
44 cp++;
45 if (*cp++ != '=')
46 goto inv;
47 while (isspace(*cp))
48 cp++;
49 if (!isxdigit(*cp))
50 goto inv;
51 baudgen_val = strtoul(cp, &cp, 16);
52 while (isspace(*cp))
53 cp++;
54 if (*cp++ != ',')
55 goto inv;
56 while (isspace(*cp))
57 cp++;
58 if (!isxdigit(*cp))
59 goto inv;
60 timeout_val = strtoul(cp, &cp, 16);
61 while (isspace(*cp))
62 cp++;
63 if (*cp++ != ',')
64 goto inv;
65 while (isspace(*cp))
66 cp++;
67 if (!isdigit(*cp))
68 goto inv;
69 prescaler = strtoul(cp, &cp, 10);
70 while (isspace(*cp))
71 cp++;
72 if (*cp++ != ',')
73 goto inv;
74 while (isspace(*cp))
75 cp++;
76 if (!isdigit(*cp))
77 goto inv;
78 extra_byte = strtoul(cp, &cp, 10);
79 while (isspace(*cp))
80 cp++;
81 if (*cp && *cp != '#')
82 goto inv;
83 /* done with parsing, get to EEPROM */
84 if (entry_idx > 31) {
85 fprintf(stderr, "%s line %d: invalid baud-entry index\n",
86 filename, lineno);
87 exit(1);
88 }
89 eerec = eeprom + entry_idx * SIZE_BAUDRATE_CFG;
90 eerec[0] = baudgen_val >> 8;
91 eerec[1] = baudgen_val;
92 eerec[2] = timeout_val >> 8;
93 eerec[3] = timeout_val;
94 eerec[4] = prescaler;
95 eerec[5] = extra_byte;
96 eerec[6] = intend_baud;
97 eerec[7] = intend_baud >> 8;
98 eerec[8] = intend_baud >> 16;
99 eerec[9] = intend_baud >> 24;
100 }
101
102 static void
103 apply_patch_8bit(filename, lineno, args)
104 char *filename, *args;
105 {
106 unsigned patch_loc, patch_val;
107 char *cp = args;
108
109 if (!isxdigit(*cp)) {
110 inv: fprintf(stderr, "%s line %d: invalid syntax for patch8\n",
111 filename, lineno);
112 exit(1);
113 }
114 patch_loc = strtoul(cp, &cp, 16);
115 while (isspace(*cp))
116 cp++;
117 if (!isxdigit(*cp))
118 goto inv;
119 patch_val = strtoul(cp, &cp, 16);
120 while (isspace(*cp))
121 cp++;
122 if (*cp && *cp != '#')
123 goto inv;
124 /* validate range */
125 if (patch_loc >= EEPROM_START_ADDR &&
126 patch_loc <= EEPROM_START_ADDR + SIZE_EEPROM - 1)
127 patch_loc -= EEPROM_START_ADDR;
128 else if (patch_loc > SIZE_EEPROM - 1) {
129 fprintf(stderr, "%s line %d: invalid patch address\n",
130 filename, lineno);
131 exit(1);
132 }
133 if (patch_val > 0xFF) {
134 fprintf(stderr,
135 "%s line %d: patch value does not fit into 8 bits\n",
136 filename, lineno);
137 exit(1);
138 }
139 /* checks done, proceed */
140 eeprom[patch_loc] = patch_val;
141 }
142
143 static void
144 apply_patch_16bit(filename, lineno, args)
145 char *filename, *args;
146 {
147 unsigned patch_loc, patch_val;
148 char *cp = args;
149
150 if (!isxdigit(*cp)) {
151 inv: fprintf(stderr, "%s line %d: invalid syntax for patch16\n",
152 filename, lineno);
153 exit(1);
154 }
155 patch_loc = strtoul(cp, &cp, 16);
156 while (isspace(*cp))
157 cp++;
158 if (!isxdigit(*cp))
159 goto inv;
160 patch_val = strtoul(cp, &cp, 16);
161 while (isspace(*cp))
162 cp++;
163 if (*cp && *cp != '#')
164 goto inv;
165 /* validate range */
166 if (patch_loc >= EEPROM_START_ADDR &&
167 patch_loc <= EEPROM_START_ADDR + SIZE_EEPROM - 2)
168 patch_loc -= EEPROM_START_ADDR;
169 else if (patch_loc > SIZE_EEPROM - 2) {
170 fprintf(stderr, "%s line %d: invalid patch address\n",
171 filename, lineno);
172 exit(1);
173 }
174 if (patch_val > 0xFFFF) {
175 fprintf(stderr,
176 "%s line %d: patch value does not fit into 16 bits\n",
177 filename, lineno);
178 exit(1);
179 }
180 /* checks done, proceed */
181 eeprom[patch_loc] = patch_val;
182 eeprom[patch_loc+1] = patch_val >> 8;
183 }
184
185 static void
186 apply_patch_vid(filename, lineno, args)
187 char *filename, *args;
188 {
189 unsigned patch_val;
190 char *cp = args;
191
192 if (!isxdigit(*cp)) {
193 inv: fprintf(stderr, "%s line %d: invalid syntax for vid\n",
194 filename, lineno);
195 exit(1);
196 }
197 patch_val = strtoul(cp, &cp, 16);
198 while (isspace(*cp))
199 cp++;
200 if (*cp && *cp != '#')
201 goto inv;
202 /* validate range */
203 if (patch_val > 0xFFFF) {
204 fprintf(stderr, "%s line %d: VID does not fit into 16 bits\n",
205 filename, lineno);
206 exit(1);
207 }
208 /* checks done, proceed */
209 eeprom[0x390] = patch_val;
210 eeprom[0x391] = patch_val >> 8;
211 }
212
213 static void
214 apply_patch_pid(filename, lineno, args)
215 char *filename, *args;
216 {
217 unsigned patch_val;
218 char *cp = args;
219
220 if (!isxdigit(*cp)) {
221 inv: fprintf(stderr, "%s line %d: invalid syntax for pid\n",
222 filename, lineno);
223 exit(1);
224 }
225 patch_val = strtoul(cp, &cp, 16);
226 while (isspace(*cp))
227 cp++;
228 if (*cp && *cp != '#')
229 goto inv;
230 /* validate range */
231 if (patch_val > 0xFFFF) {
232 fprintf(stderr, "%s line %d: PID does not fit into 16 bits\n",
233 filename, lineno);
234 exit(1);
235 }
236 /* checks done, proceed */
237 eeprom[0x392] = patch_val;
238 eeprom[0x393] = patch_val >> 8;
239 }
240
241 static void
242 set_string_desc(start_offset, str)
243 unsigned start_offset;
244 char *str;
245 {
246 char *cp;
247 u_char *dp;
248
249 dp = eeprom + start_offset;
250 *dp++ = strlen(str) * 2 + 2;
251 *dp++ = 0x03;
252 for (cp = str; *cp; ) {
253 *dp++ = *cp++;
254 *dp++ = 0;
255 }
256 }
257
258 static void
259 set_manuf_string(filename, lineno, arg)
260 char *filename, *arg;
261 {
262 if (strlen(arg) > 29) {
263 fprintf(stderr, "%s line %d: manuf string is too long\n",
264 filename, lineno);
265 exit(1);
266 }
267 set_string_desc(0x3C3, arg);
268 }
269
270 static void
271 set_product_string(filename, lineno, arg)
272 char *filename, *arg;
273 {
274 if (strlen(arg) > 126) {
275 fprintf(stderr, "%s line %d: product string is too long\n",
276 filename, lineno);
277 exit(1);
278 }
279 set_string_desc(0x208, arg);
280 }
281
282 static void
283 set_serial_string(filename, lineno, arg)
284 char *filename, *arg;
285 {
286 if (strlen(arg) > 63) {
287 fprintf(stderr, "%s line %d: serial string is too long\n",
288 filename, lineno);
289 exit(1);
290 }
291 set_string_desc(0x307, arg);
292 }
293
294 static void
295 apply_eeprom_patch_int(filename, inf)
296 char *filename;
297 FILE *inf;
298 {
299 char linebuf[1024];
300 int lineno;
301 char *cp, *np;
302
303 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
304 cp = index(linebuf, '\n');
305 if (!cp) {
306 fprintf(stderr,
307 "%s line %d: too long or unterminated\n",
308 filename, lineno);
309 exit(1);
310 }
311 *cp = '\0';
312 for (cp = linebuf; isspace(*cp); cp++)
313 ;
314 if (*cp == '\0' || *cp == '#')
315 continue;
316 for (np = cp; *cp && !isspace(*cp); cp++)
317 ;
318 if (*cp)
319 *cp++ = '\0';
320 while (isspace(*cp))
321 cp++;
322 if (*cp == '\0' || *cp == '#') {
323 fprintf(stderr,
324 "%s line %d: \"%s\" setting without argument\n",
325 filename, lineno, np);
326 exit(1);
327 }
328 if (!strcmp(np, "baud-entry"))
329 apply_baud_entry(filename, lineno, cp);
330 else if (!strcmp(np, "patch8"))
331 apply_patch_8bit(filename, lineno, cp);
332 else if (!strcmp(np, "patch16"))
333 apply_patch_16bit(filename, lineno, cp);
334 else if (!strcmp(np, "vid"))
335 apply_patch_vid(filename, lineno, cp);
336 else if (!strcmp(np, "pid"))
337 apply_patch_pid(filename, lineno, cp);
338 else if (!strcmp(np, "manuf"))
339 set_manuf_string(filename, lineno, cp);
340 else if (!strcmp(np, "product"))
341 set_product_string(filename, lineno, cp);
342 else if (!strcmp(np, "serial"))
343 set_serial_string(filename, lineno, cp);
344 else {
345 fprintf(stderr, "%s line %d: unknown \"%s\" setting\n",
346 filename, lineno, np);
347 exit(1);
348 }
349 }
350 }
351
352 static FILE *
353 open_with_search(req_filename)
354 char *req_filename;
355 {
356 char pathbuf[256];
357 FILE *f;
358
359 if (!index(req_filename, '/') && strlen(req_filename) < 128) {
360 sprintf(pathbuf, "%s/%s", cp2102_install_dir, req_filename);
361 f = fopen(pathbuf, "r");
362 if (f)
363 return f;
364 }
365 f = fopen(req_filename, "r");
366 return f;
367 }
368
369 void
370 apply_eeprom_patch_file(filename)
371 char *filename;
372 {
373 FILE *inf;
374
375 inf = open_with_search(filename);
376 if (!inf) {
377 perror(filename);
378 exit(1);
379 }
380 apply_eeprom_patch_int(filename, inf);
381 fclose(inf);
382 }
383
384 void
385 apply_eeprom_patch_baud(baud_spec_name)
386 char *baud_spec_name;
387 {
388 char pathbuf[256];
389 FILE *inf;
390
391 if (strlen(baud_spec_name) > 63) {
392 fprintf(stderr, "error: no buffer overflow attacks, please\n");
393 exit(1);
394 }
395 sprintf(pathbuf, "%s/baudtab-%s", cp2102_install_dir, baud_spec_name);
396 inf = fopen(pathbuf, "r");
397 if (!inf) {
398 perror(pathbuf);
399 exit(1);
400 }
401 apply_eeprom_patch_int(pathbuf, inf);
402 fclose(inf);
403 }