FreeCalypso > hg > freecalypso-reveng
comparison fluid-mnf/flash.c @ 311:9cecc930d78f
fluid-mnf: original source from TI,
defenestrated line endings and rearranged directory structure,
but no *.[ch] source file content changes yet
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 29 Feb 2020 05:36:07 +0000 |
parents | |
children | f89a20e7adc7 |
comparison
equal
deleted
inserted
replaced
310:ae39d76d5b7a | 311:9cecc930d78f |
---|---|
1 /****************************************************************************** | |
2 * FLUID (Flash Loader Utility Independent of Device) | |
3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com | |
4 * | |
5 * Copyright Texas Instruments, 2001. | |
6 * Mads Meisner-Jensen, mmj@ti.com. | |
7 * | |
8 * Flash device database and lookup | |
9 * | |
10 * $Id: flash.c 1.26 Wed, 30 Oct 2002 12:09:08 +0100 tsj $ | |
11 * | |
12 ******************************************************************************/ | |
13 | |
14 #include "fluid.h" | |
15 #include "misc.h" | |
16 #include "flash.h" | |
17 #include "trace.h" | |
18 | |
19 #include <stdio.h> | |
20 #include <string.h> | |
21 #include <ctype.h> | |
22 #include <stdlib.h> | |
23 | |
24 | |
25 /****************************************************************************** | |
26 * Global, Static definitions | |
27 ******************************************************************************/ | |
28 | |
29 const struct algorithm_s algorithms[] = { | |
30 { ALGORITHM_AMD, "amd" }, | |
31 { ALGORITHM_INTEL, "intel" }, | |
32 { ALGORITHM_INTEL_BW, "intel_bw" }, | |
33 { ALGORITHM_MITSUBISHI, "mitsubishi" }, | |
34 { ALGORITHM_SST, "sst" }, | |
35 { 0, "unknown" } | |
36 }; | |
37 | |
38 struct manufact_s manufacturers[] = { | |
39 { MANUFACT_AMD, "AMD" }, | |
40 { MANUFACT_ATMEL, "Atmel" }, | |
41 { MANUFACT_FUJITSU, "Fujitsu" }, | |
42 { MANUFACT_INTEL, "Intel" }, | |
43 { MANUFACT_MXIC, "MXIC" }, | |
44 { MANUFACT_MITSUBISHI, "Mitsubishi" }, | |
45 { MANUFACT_SAMSUNG, "Samsung" }, | |
46 { MANUFACT_SHARP, "Sharp" }, | |
47 { MANUFACT_STM, "STM" }, | |
48 { MANUFACT_SST, "SST" }, | |
49 { MANUFACT_TOSHIBA, "Toshiba" }, | |
50 { 0x00, "Unknown" } | |
51 }; | |
52 | |
53 | |
54 /****************************************************************************** | |
55 * Default Device Database | |
56 ******************************************************************************/ | |
57 | |
58 struct memmap_s map_63x64_8x8 = { | |
59 0, | |
60 "63x64_8x8kB", | |
61 63 + 8, | |
62 { | |
63 { 0x000000, 0x10000 }, { 0x010000, 0x10000 }, | |
64 { 0x020000, 0x10000 }, { 0x030000, 0x10000 }, | |
65 { 0x040000, 0x10000 }, { 0x050000, 0x10000 }, | |
66 { 0x060000, 0x10000 }, { 0x070000, 0x10000 }, | |
67 { 0x080000, 0x10000 }, { 0x090000, 0x10000 }, | |
68 { 0x0A0000, 0x10000 }, { 0x0B0000, 0x10000 }, | |
69 { 0x0C0000, 0x10000 }, { 0x0D0000, 0x10000 }, | |
70 { 0x0E0000, 0x10000 }, { 0x0F0000, 0x10000 }, | |
71 | |
72 { 0x100000, 0x10000 }, { 0x110000, 0x10000 }, | |
73 { 0x120000, 0x10000 }, { 0x130000, 0x10000 }, | |
74 { 0x140000, 0x10000 }, { 0x150000, 0x10000 }, | |
75 { 0x160000, 0x10000 }, { 0x170000, 0x10000 }, | |
76 { 0x180000, 0x10000 }, { 0x190000, 0x10000 }, | |
77 { 0x1A0000, 0x10000 }, { 0x1B0000, 0x10000 }, | |
78 { 0x1C0000, 0x10000 }, { 0x1D0000, 0x10000 }, | |
79 { 0x1E0000, 0x10000 }, { 0x1F0000, 0x10000 }, | |
80 | |
81 { 0x200000, 0x10000 }, { 0x210000, 0x10000 }, | |
82 { 0x220000, 0x10000 }, { 0x230000, 0x10000 }, | |
83 { 0x240000, 0x10000 }, { 0x250000, 0x10000 }, | |
84 { 0x260000, 0x10000 }, { 0x270000, 0x10000 }, | |
85 { 0x280000, 0x10000 }, { 0x290000, 0x10000 }, | |
86 { 0x2A0000, 0x10000 }, { 0x2B0000, 0x10000 }, | |
87 { 0x2C0000, 0x10000 }, { 0x2D0000, 0x10000 }, | |
88 { 0x2E0000, 0x10000 }, { 0x2F0000, 0x10000 }, | |
89 | |
90 { 0x300000, 0x10000 }, { 0x310000, 0x10000 }, | |
91 { 0x320000, 0x10000 }, { 0x330000, 0x10000 }, | |
92 { 0x340000, 0x10000 }, { 0x350000, 0x10000 }, | |
93 { 0x360000, 0x10000 }, { 0x370000, 0x10000 }, | |
94 { 0x380000, 0x10000 }, { 0x390000, 0x10000 }, | |
95 { 0x3A0000, 0x10000 }, { 0x3B0000, 0x10000 }, | |
96 { 0x3C0000, 0x10000 }, { 0x3D0000, 0x10000 }, | |
97 { 0x3E0000, 0x10000 }, | |
98 | |
99 { 0x3F0000, 0x02000 }, { 0x3F2000, 0x02000 }, | |
100 { 0x3F4000, 0x02000 }, { 0x3F6000, 0x02000 }, | |
101 { 0x3F8000, 0x02000 }, { 0x3FA000, 0x02000 }, | |
102 { 0x3FC000, 0x02000 }, { 0x3FE000, 0x02000 }, | |
103 } | |
104 }; | |
105 | |
106 struct memmap_s *memmaps = &map_63x64_8x8; | |
107 | |
108 // Default B-Sample device | |
109 struct device_s device_fujitsu_dl323t = { | |
110 0, | |
111 ALGORITHM_AMD, | |
112 MANUFACT_FUJITSU, | |
113 0x2250, | |
114 "MBM29DL323DT", | |
115 0, | |
116 0, | |
117 &map_63x64_8x8 | |
118 }; | |
119 | |
120 // Default C-Sample device | |
121 struct device_s device_amd_dl322t = { | |
122 &device_fujitsu_dl323t, // link to next (previous) device defintion | |
123 ALGORITHM_AMD, | |
124 MANUFACT_AMD, | |
125 0x2255, | |
126 "Am29DL322DT", | |
127 0, | |
128 0, | |
129 &map_63x64_8x8 | |
130 }; | |
131 | |
132 struct device_s *devices = &device_amd_dl322t; | |
133 | |
134 | |
135 /****************************************************************************** | |
136 * Device file reading and parsing | |
137 ******************************************************************************/ | |
138 | |
139 #define INBUF_SIZE 1024 | |
140 | |
141 static char inbuf[INBUF_SIZE]; | |
142 static char *pin; | |
143 static FILE *fp; | |
144 static int linenum; | |
145 | |
146 static char string[1024]; | |
147 static int length; | |
148 static int number; | |
149 | |
150 enum ParserTokens { | |
151 TOKEN_EOF, | |
152 TOKEN_STRING, | |
153 TOKEN_NUMBER, | |
154 TOKEN_KEYWORD | |
155 }; | |
156 | |
157 enum ParserKeywords { | |
158 KEYWORD_NONE, | |
159 KEYWORD_DEVICE, | |
160 KEYWORD_MEMMAP | |
161 }; | |
162 | |
163 void parser_error(int error) | |
164 { | |
165 fprintf(stderr, "At line %d, ", linenum); | |
166 main_fatal(error); | |
167 } | |
168 | |
169 void file_read_devices(char *filename) | |
170 { | |
171 int token, i, n = 0; | |
172 struct device_s *device; | |
173 struct memmap_s *memmap; | |
174 | |
175 flowf(BLABBER, "Reading '%s': ", filename); | |
176 | |
177 // First look for file in current directory. Then look for it in the | |
178 // directory where the fluid executable was found. | |
179 if ((fp = fopen(filename, "rt")) == NULL) | |
180 { | |
181 char buf[256]; | |
182 | |
183 if (pathname_make(buf, sizeof(buf), argv_0, filename) < 0) | |
184 main_fatal(E_BUFFER); | |
185 | |
186 flowf(DEBUG, "(looking for '%s') ", buf); | |
187 | |
188 if ((fp = fopen(buf, "rt")) == NULL) { | |
189 fprintf(stderr, "WARNING: file '%s' not found. Using default device database.\n", filename); | |
190 return; | |
191 } | |
192 } | |
193 | |
194 devices = (struct device_s *) 0; | |
195 memmaps = (struct memmap_s *) 0; | |
196 | |
197 pin = inbuf; | |
198 inbuf[0] = '\n'; | |
199 linenum = 0; | |
200 | |
201 // Each loop represents one block/statement of the file | |
202 while ((token = get_keyword()) != E_PARSER_EOF) { | |
203 switch (token) { | |
204 case KEYWORD_MEMMAP: | |
205 tr(TrBegin|TrParser, "keyword: memmap {\n"); | |
206 if ((token = get_string()) < 0) | |
207 parser_error(token); | |
208 | |
209 if ((memmap = malloc(sizeof(struct memmap_s) + length + 1)) == NULL) | |
210 parser_error(E_MEMORY); | |
211 memmap->name = (char *) memmap + sizeof(struct memmap_s); | |
212 strcpy(memmap->name, string); | |
213 | |
214 if ((token = get_token()) != '{') | |
215 parser_error(E_PARSER_SYNTAX); | |
216 | |
217 i = 0; | |
218 while ((token = get_token()) == TOKEN_NUMBER) | |
219 { | |
220 memmap->sectors[i].addr = number; | |
221 | |
222 if ((token = get_number()) < 0) | |
223 parser_error(token); | |
224 memmap->sectors[i].size = number; | |
225 | |
226 i++; | |
227 } | |
228 if (token != '}') | |
229 parser_error(E_PARSER_END_BRACE); | |
230 | |
231 memmap->size = i; | |
232 | |
233 // Append to linked list | |
234 memmap->next = memmaps; | |
235 memmaps = memmap; | |
236 | |
237 tr(TrEnd|TrParser, "}\n"); | |
238 break; | |
239 | |
240 case KEYWORD_DEVICE: | |
241 tr(TrBegin|TrParser, "keyword: device {\n"); | |
242 if ((token = get_string()) < 0) | |
243 parser_error(token); | |
244 if ((device = malloc(sizeof(struct device_s) + length + 1)) == NULL) | |
245 parser_error(E_MEMORY); | |
246 device->name = (char *) device + sizeof(struct device_s); | |
247 strcpy(device->name, string); | |
248 | |
249 if ((token = get_number()) < 0) | |
250 parser_error(token); | |
251 device->manufacturer_id = number; | |
252 | |
253 if ((token = get_number()) < 0) | |
254 parser_error(token); | |
255 device->device_id = number; | |
256 | |
257 if ((token = get_string()) < 0) | |
258 parser_error(token); | |
259 device->algorithm_id = algorithm_id_lookup_by_name(string); | |
260 if (device->algorithm_id == 0) | |
261 parser_error(E_PARSER_ALGORITHM); | |
262 | |
263 if ((token = get_string()) < 0) | |
264 parser_error(token); | |
265 device->memmap = memmap_lookup_by_name(string); | |
266 if (device->memmap == 0) | |
267 parser_error(E_PARSER_MEMMAP); | |
268 | |
269 // Append to linked list | |
270 device->next = devices; | |
271 devices = device; | |
272 | |
273 tr(TrEnd|TrParser, "}\n"); | |
274 break; | |
275 default: | |
276 parser_error(E_PARSER_KEYWORD); | |
277 } | |
278 n++; | |
279 } | |
280 | |
281 flowf(BLABBER, "(%d blocks read) ok.\n", n); | |
282 } | |
283 | |
284 int get_next_line(void) | |
285 { | |
286 int result; | |
287 | |
288 result = (fgets(inbuf, INBUF_SIZE, fp) != NULL); | |
289 | |
290 pin = inbuf; | |
291 linenum++; | |
292 | |
293 tr(TrParser, "get_next_line() (%d) %d ", result); | |
294 | |
295 return result; | |
296 } | |
297 | |
298 int get_token(void) | |
299 { | |
300 char *pin_start, *pin_end; | |
301 int whitespace; | |
302 | |
303 { | |
304 char tmp[8]; | |
305 for (whitespace = 0; whitespace < 7; whitespace++) | |
306 tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]); | |
307 tmp[7] = 0; | |
308 tr(TrParser, "get_token() ('%s...')", tmp); | |
309 } | |
310 | |
311 whitespace = 1; | |
312 | |
313 while (whitespace) | |
314 { | |
315 if (*pin == ' ' || *pin == '\t' || *pin == '\n') { | |
316 // Skip white-space | |
317 tr(TrParser, " skip white-space {"); | |
318 while (*pin == ' ' || *pin == '\t' || *pin == '\n') | |
319 { | |
320 while (*pin == ' ' || *pin == '\t') | |
321 pin++; | |
322 | |
323 // If end of line, read the next line | |
324 if (*pin == '\n') { | |
325 if (get_next_line() == 0) | |
326 return TOKEN_EOF; | |
327 } | |
328 } | |
329 tr(TrCont|TrParser, "}"); | |
330 } | |
331 else if (pin[0] == '/' && pin[1] == '*') { | |
332 // Skip comment | |
333 tr(TrParser, " skip comment {"); | |
334 while (pin[0] != '*' || pin[1] != '/') | |
335 { | |
336 while ((pin[0] != '*' || pin[1] != '/') && *pin != '\n') | |
337 pin++; | |
338 | |
339 // If end of line, read the next line | |
340 if (*pin == '\n') { | |
341 if (get_next_line() == 0) | |
342 return TOKEN_EOF; | |
343 } | |
344 else { | |
345 pin += 2; | |
346 break; | |
347 } | |
348 } | |
349 tr(TrCont|TrParser, "}"); | |
350 } | |
351 else { | |
352 whitespace = 0; | |
353 } | |
354 } | |
355 | |
356 { | |
357 char tmp[8]; | |
358 for (whitespace = 0; whitespace < 7; whitespace++) | |
359 tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]); | |
360 tmp[7] = 0; | |
361 tr(TrCont|TrParser, " ('%s...')\n", tmp); | |
362 } | |
363 | |
364 // See if token is a string | |
365 if (isalpha(*pin) || *pin == '_') { | |
366 pin_start = pin; | |
367 while (isalnum(*pin) || *pin == '_') | |
368 pin++; | |
369 length = pin - pin_start; | |
370 strncpy(string, pin_start, length); | |
371 string[length] = 0; | |
372 return TOKEN_STRING; | |
373 } | |
374 | |
375 // See if token is a number | |
376 if (isdigit(*pin)) { | |
377 number = (int) strtol(pin, &pin_end, 0); | |
378 pin = pin_end; | |
379 if (*pin_end == 'k') { | |
380 number *= 1024; | |
381 pin++; | |
382 } | |
383 return TOKEN_NUMBER; | |
384 } | |
385 | |
386 // Token is a character | |
387 return *pin++; | |
388 } | |
389 | |
390 int get_keyword(void) | |
391 { | |
392 int token; | |
393 | |
394 token = get_token(); | |
395 tr(TrParser, "get_keyword() (%d) ", token); | |
396 | |
397 if (token == TOKEN_EOF) | |
398 return E_PARSER_EOF; | |
399 | |
400 if (token != TOKEN_STRING) | |
401 return E_PARSER_KEYWORD; | |
402 | |
403 if (strcmp("memmap", string) == 0) | |
404 token = KEYWORD_MEMMAP; | |
405 else if (strcmp("device", string) == 0) | |
406 token = KEYWORD_DEVICE; | |
407 else | |
408 token = E_PARSER_KEYWORD; | |
409 | |
410 tr(TrCont|TrParser, "%d\n", token); | |
411 return token; | |
412 } | |
413 | |
414 int get_string(void) | |
415 { | |
416 int token; | |
417 | |
418 token = get_token(); | |
419 tr(TrParser, "get_string() (%d) ", token); | |
420 | |
421 if (token == TOKEN_EOF) | |
422 return E_PARSER_EOF; | |
423 | |
424 if (token != TOKEN_STRING) | |
425 return E_PARSER_STRING; | |
426 | |
427 tr(TrCont|TrParser, "'%s'\n", string); | |
428 return 0; | |
429 } | |
430 | |
431 int get_number(void) | |
432 { | |
433 int token; | |
434 | |
435 token = get_token(); | |
436 tr(TrParser, "get_number() (%d) ", token); | |
437 | |
438 if (token == TOKEN_EOF) | |
439 return E_PARSER_EOF; | |
440 | |
441 if (token != TOKEN_NUMBER) | |
442 return E_PARSER_NUMBER; | |
443 | |
444 tr(TrCont|TrParser, "0x%X\n", number); | |
445 return 0; | |
446 } | |
447 | |
448 | |
449 /****************************************************************************** | |
450 * Functions | |
451 ******************************************************************************/ | |
452 | |
453 // Estimate the time taken for erasure and programming of the flash | |
454 // device. <bytes> is the number of bytes to program. | |
455 int time_compute(struct device_s *device, | |
456 int sectors, int bytes, int chunks, | |
457 int *time_erase, int *time_program, int *time_transfer) | |
458 { | |
459 int te = 0; // sector erase time in milli seconds | |
460 int tp = 16; // 16-bit word program time in micro seconds | |
461 int tdt, tco, trp; | |
462 | |
463 switch (device->algorithm_id) { | |
464 case ALGORITHM_AMD: te = 700; break; | |
465 case ALGORITHM_INTEL: te = 800; break; | |
466 case ALGORITHM_INTEL_BW: te = 1300; break; | |
467 case ALGORITHM_MITSUBISHI: te = 40; break; | |
468 case ALGORITHM_SST: te = 20; break; | |
469 } | |
470 *time_erase = te * sectors; | |
471 | |
472 // Data transmission time: with 12 bytes per chunk | |
473 tdt = (bytes + 12 * chunks) / (arg_uart_baudrate / 10) * 1000; | |
474 | |
475 // Communication overhead time: 2 waits of 10ms per chunk. | |
476 tco = chunks * 2 * 10; | |
477 | |
478 *time_transfer = tdt + tco; | |
479 | |
480 // Raw programming time: | |
481 *time_program = trp = (bytes / 2) * tp / 1000; | |
482 | |
483 tr(TrUtility, "tdt = %d\n", tdt); | |
484 tr(TrUtility, "tco = %d\n", tco); | |
485 tr(TrUtility, "trp = %d\n", trp); | |
486 | |
487 return *time_erase + *time_transfer; | |
488 } | |
489 | |
490 void device_print(struct device_s *device, char format) | |
491 { | |
492 int device_size = | |
493 (device->memmap->sectors[device->memmap->size - 1].addr + | |
494 device->memmap->sectors[device->memmap->size - 1].size) / | |
495 (1024 * 1024 / 8); | |
496 | |
497 if (format == 'l') { | |
498 printf("%s %s (0x%02X, 0x%04X). %dMb in %d sectors, %s algorithm", | |
499 manufacturer_name_lookup_by_id(device->manufacturer_id), | |
500 device->name, | |
501 device->manufacturer_id, | |
502 device->device_id, | |
503 device_size, | |
504 device->memmap->size, | |
505 algorithm_name_lookup_by_id(device->algorithm_id)); | |
506 } | |
507 else if (format == 's') { | |
508 printf("(0x%02X, 0x%04X) %s %s", | |
509 device->manufacturer_id, | |
510 device->device_id, | |
511 manufacturer_name_lookup_by_id(device->manufacturer_id), | |
512 device->name); | |
513 } | |
514 } | |
515 | |
516 void devices_list(void) | |
517 { | |
518 struct device_s *device = devices; | |
519 | |
520 while (device != NULL) { | |
521 device_print(device, 'l'); | |
522 putchar('\n'); | |
523 device = device->next; | |
524 } | |
525 } | |
526 | |
527 struct device_s *device_lookup_by_id(int m, int d) | |
528 { | |
529 struct device_s *device = devices; | |
530 | |
531 while (device != NULL) { | |
532 if ((m & 0xFF) == device->manufacturer_id && d == device->device_id) | |
533 return device; | |
534 device = device->next; | |
535 } | |
536 return (struct device_s *) 0; | |
537 } | |
538 | |
539 struct device_s *device_lookup_by_name(char *name) | |
540 { | |
541 struct device_s *device = devices; | |
542 | |
543 while (device != NULL) { | |
544 if (strcmp(name, device->name) == 0) | |
545 return device; | |
546 device = device->next; | |
547 } | |
548 return (struct device_s *) 0; | |
549 | |
550 } | |
551 | |
552 struct memmap_s *memmap_lookup_by_name(char *name) | |
553 { | |
554 struct memmap_s *memmap = memmaps; | |
555 | |
556 while (memmap != NULL) { | |
557 if (strcmp(name, memmap->name) == 0) | |
558 return memmap; | |
559 memmap = memmap->next; | |
560 } | |
561 return (struct memmap_s *) 0; | |
562 } | |
563 | |
564 char *manufacturer_name_lookup_by_id(int id) | |
565 { | |
566 int i = 0; | |
567 | |
568 while (manufacturers[i].id != 0) { | |
569 if (manufacturers[i].id == id) | |
570 return manufacturers[i].name; | |
571 i++; | |
572 } | |
573 | |
574 return manufacturers[i].name; | |
575 } | |
576 | |
577 int manufacturer_id_lookup_by_name(char *name) | |
578 { | |
579 int i = 0; | |
580 | |
581 while (manufacturers[i].id != 0) { | |
582 if (strcmp(manufacturers[i].name, name) == 0) | |
583 return manufacturers[i].id; | |
584 i++; | |
585 } | |
586 | |
587 return 0; | |
588 } | |
589 | |
590 char *algorithm_name_lookup_by_id(int id) | |
591 { | |
592 int i = 0; | |
593 | |
594 while (algorithms[i].id != 0) { | |
595 if (algorithms[i].id == id) | |
596 return algorithms[i].name; | |
597 i++; | |
598 } | |
599 | |
600 return algorithms[i].name; | |
601 } | |
602 | |
603 int algorithm_id_lookup_by_name(char *name) | |
604 { | |
605 int i = 0; | |
606 | |
607 while (algorithms[i].id != 0) { | |
608 if (strcmp(algorithms[i].name, name) == 0) | |
609 return algorithms[i].id; | |
610 i++; | |
611 } | |
612 | |
613 return 0; | |
614 } |