1 /*************************************************************************************
2 * FILE PURPOSE: Create an I2C rom with multiple boot parameter sections and
3 * programs
4 *************************************************************************************
5 * FILE NAME: romparse.c
6 *
7 * DESCRIPTION: Creates a ccs hex file which contains the i2c eprom boot parameter
8 * tables as well as any code.
9 *
10 *************************************************************************************/
11 #include <stdio.h>
12 #include <string.h>
13 #include <malloc.h>
14 #include "rparse.tab.h"
15 #include "romparse.h"
17 /*************************************************************************************
18 * Definition: fixed i2c map locations
19 *************************************************************************************/
20 #define PCI_PARAM_BASE (NUM_BOOT_PARAM_TABLES * 0x80)
21 #define DATA_BASE (PCI_PARAM_BASE + PCI_EEAI_PARAM_SIZE)
25 /*************************************************************************************
26 * Declaration: The flex input file is assigned based on the command line
27 *************************************************************************************/
28 extern FILE *yyin;
30 /*************************************************************************************
31 * Declaration: currentType identifies the current parse mode, either SECTION
32 * or LAYOUT.
33 *************************************************************************************/
34 int currentType;
36 /*************************************************************************************
37 * Declaration: The boot parameter tables. The current table is copied into position
38 * when the section parse is complete.
39 *************************************************************************************/
40 BOOT_PARAMS_T boot_params[NUM_BOOT_PARAM_TABLES];
41 BOOT_PARAMS_T current_table;
42 int current_file; /* Identifies the program file in the current table */
43 int ctable_index = -1; /* Destination of current table */
44 int max_index = 0; /* maximum table index, used for compacting output */
46 /************************************************************************************
47 * Declaration: Layout tables.
48 ************************************************************************************/
49 layout_t layouts[MAX_LAYOUTS]; /* Array of layout structures */
50 int currentLayout = 0; /* Currently active layout */
52 /************************************************************************************
53 * Declaration: The structure storing the program data files, and the number of
54 * programs used.
55 ************************************************************************************/
56 progFile_t progFile[NUM_BOOT_PARAM_TABLES];
57 int nProgFiles = 0;
59 /************************************************************************************
60 * Declaration: The PCI parameter structure
61 ************************************************************************************/
62 pciFile_t pciFile;
63 int pciSet = 0;
65 /*************************************************************************************
66 * Declaration: The next free address in the ROM for general data usage. For the
67 * start address there is room for the initial boot parameter tables,
68 * plus room for the PCI eeai config.
69 *************************************************************************************/
70 int romBase = DATA_BASE;
73 /*************************************************************************************
74 * Declaration: Args passed in from the command line
75 *************************************************************************************/
76 char *inputFile;
77 int compact = 0;
80 /*************************************************************************************
81 * FUNCTION PURPOSE: flex/bison required support functions.
82 *************************************************************************************
83 * DESCRIPTION: yyerror and yywrap are required to support flex and/or bison parsing
84 * of the parameter description file. yyerror directly reports the
85 * error, yywrap is unused.
86 *************************************************************************************/
87 void yyerror (char *s)
88 {
89 fprintf (stderr, "flex/bison error is %s\n", s);
90 } /* yyerror */
92 void yywrap (void)
93 {
94 } /* yywrap */
96 /*************************************************************************************
97 * FUNCTION PURPOSE: Initialize a boot table
98 *************************************************************************************
99 * DESCRIPTION: Sets a boot parameter table to 0s
100 *************************************************************************************/
101 void initTable (BOOT_PARAMS_T *current_table)
102 {
103 memset (current_table, 0, sizeof(BOOT_PARAMS_T));
104 }
106 /*************************************************************************************
107 * FUNCTION PURPOSE: Initialize the program data file table
108 *************************************************************************************
109 * DESCRIPTION: The size and tags are all setup
110 *************************************************************************************/
111 void initProgFile (void)
112 {
113 int i, j;
115 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
116 progFile[i].sizeBytes = 0;
117 progFile[i].align = 0;
119 for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)
120 progFile[i].tag[j] = -1;
122 }
124 }
127 /*************************************************************************************
128 * FUNCTION PURPOSE: Set the currently active parse type
129 *************************************************************************************
130 * DESCRIPTION: Indicates if the subsequent parameters belong to a section or
131 * a layout
132 *************************************************************************************/
133 void rBegin (int blockType)
134 {
135 currentType = blockType;
136 }
138 /*************************************************************************************
139 * FUNCTION PURPOSE: Initialize a layout structure
140 *************************************************************************************
141 * DESCRIPTION: The layout is set to the initial state
142 *************************************************************************************/
143 void initLayout (layout_t *cl)
144 {
146 cl->nFiles = 0;
147 cl->dev_addr = 0x50;
148 cl->address = 0;
149 cl->align = 0;
151 }
153 /*************************************************************************************
154 * FUNCTION PURPOSE: Complete a layout
155 *************************************************************************************
156 * DESCRIPTION: The parser has found a complete layout specification. Complete
157 * a layout structure
158 *************************************************************************************/
159 void setLayout (void)
160 {
161 int i;
162 int currentAlign;
163 int newAlign;
165 for (i = 0; i < layouts[currentLayout].nFiles; i++) {
166 currentAlign = progFile[layouts[currentLayout].file[i]].align;
167 newAlign = layouts[currentLayout].align;
169 if (newAlign > currentAlign)
170 progFile[layouts[currentLayout].file[i]].align = newAlign;
172 }
174 currentLayout += 1; /* Advance to the next layout */
176 if (currentLayout < MAX_LAYOUTS)
177 initLayout (&layouts[currentLayout]);
179 }
183 /*************************************************************************************
184 * FUNCTION PURPOSE: Complete a section
185 *************************************************************************************
186 * DESCRIPTION: The parser has detected a complete section. Copy the section into
187 * it's correct table location.
188 *************************************************************************************/
189 void section (void)
190 {
191 int i;
193 /* It's an error if no section value has been declared */
194 if (ctable_index == -1) {
195 fprintf (stderr, "romparse: the section did not have a boot paramter index specified\n");
196 exit (-1);
197 }
199 /* Make sure the table is in range */
200 if (ctable_index >= NUM_BOOT_PARAM_TABLES) {
201 fprintf (stderr, "romparse: The section index is too large (max %d)\n", NUM_BOOT_PARAM_TABLES-1);
202 exit (-1);
203 }
205 /* The length must be set. Currently this program only supports I2C mode, so the
206 * length is fixed */
207 current_table.common.length = 30;
208 current_table.common.checksum = 0;
210 /* Copy the table */
211 memcpy (&boot_params[ctable_index], ¤t_table, sizeof (BOOT_PARAMS_T));
212 initTable (¤t_table);
214 /* Track the maximum table index */
215 if (ctable_index > max_index)
216 max_index = ctable_index;
218 /* If the section referenced a data file, link the data file back to this section */
219 if (current_file >= 0) {
220 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
221 if (progFile[current_file].tag[i] < 0)
222 progFile[current_file].tag[i] = ctable_index;
223 break;
224 }
225 }
227 ctable_index = -1;
228 current_file = -1;
230 } /* section */
232 /***************************************************************************************
233 * FUNCTION PURPOSE: Open a ccs hex file and read in the data.
234 ***************************************************************************************
235 * DESCRIPTION: Reads a ccs hex format data file, loads the file into the
236 * next program file structure. Returns the index of the just loaded
237 * table.
238 ***************************************************************************************/
239 int openProgFile (char *fname)
240 {
241 FILE *str;
242 int a, b, c, d, e;
243 int i;
244 char iline[132];
246 /* Store the file name */
247 strcpy (progFile[nProgFiles].fname, fname);
249 /* Open the data file */
250 str = fopen (fname, "r");
251 if (str == NULL) {
252 fprintf (stderr, "romparse: Could not open file %s\n", fname);
253 exit (-1);
254 }
256 /* Read the one line ccs header. The length field in terms of lines */
257 fgets (iline, 132, str);
258 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
259 progFile[nProgFiles].sizeBytes = e * 4; /* Length was in 4 byte words */
261 /* Read in the data */
262 for (i = 0; i < e; i++) {
263 fgets (iline, 132, str);
264 sscanf (&(iline[2]), "%x", &((progFile[nProgFiles]).data[i]));
265 }
267 fclose (str);
269 i = nProgFiles;
270 nProgFiles += 1;
272 return (i);
274 } /* openProgFile */
276 /***************************************************************************************
277 * FUNCTION PURPOSE: Load the PCI paramter section
278 ***************************************************************************************
279 * DESCRIPTION: Loads the PCI parameter section and stores it in the rom. */
280 int setPciParams (char *fname)
281 {
282 FILE *str;
283 int a, b, c, d, e;
284 int i;
285 char iline[132];
286 char *z;
288 if (pciSet) {
289 fprintf (stderr, "romparse: PCI parameters specified more then once\n");
290 exit (-1);
291 }
293 /* the input string still contains the quotes. Remove them here */
294 z = &fname[1];
295 *strchr (z, '"') = '\0';
297 /* Store the file name */
298 strcpy (pciFile.fname, z);
300 /* Open the data file */
301 str = fopen (z, "r");
302 if (str == NULL) {
303 fprintf (stderr, "romparse: Could not open pci file %s\n", fname);
304 exit (-1);
305 }
307 /* The address of the pci params is currently fixed */
308 pciFile.addressBytes = PCI_PARAM_BASE;
310 /* Read the one line ccs header. The length field is in terms of lines */
311 fgets (iline, 132, str);
312 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
313 pciFile.sizeBytes = e * 4; /* Convert length to bytes */
315 /* Read in the data */
316 for (i = 0; i < e; i++) {
317 fgets (iline, 132, str);
318 sscanf (&(iline[2]), "%x", &(pciFile.data[i]));
319 }
321 pciSet = 1;
323 return (0);
325 } /* setPciParams */
329 /***************************************************************************************
330 * FUNCTION PURPOSE: Store an assignment
331 ***************************************************************************************
332 * DESCRIPTION: Stores an assigned value into the current boot parameter table
333 ***************************************************************************************/
334 void assignKeyVal (int field, int value)
335 {
337 if ((currentType == SECTION) && (currentLayout >= MAX_LAYOUTS)) {
338 fprintf (stderr, "romparse: Too many layout sections (max = %d\n", MAX_LAYOUTS);
339 return;
340 }
344 switch (field) {
346 case BOOT_MODE: current_table.common.boot_mode = value;
347 break;
349 case PARAM_INDEX: ctable_index = value;
350 break;
352 case OPTIONS: current_table.i2c.options = value;
353 break;
355 case MULTI_I2C_ID: current_table.i2c.multi_i2c_id = value;
356 break;
358 case MY_I2C_ID: current_table.i2c.my_i2c_id = value;
359 break;
361 case CORE_FREQ_MHZ: current_table.i2c.core_freq_mhz = value;
362 break;
364 case I2C_CLK_FREQ_KHZ: current_table.i2c.i2c_clk_freq_khz = value;
365 break;
367 case NEXT_DEV_ADDR: current_table.i2c.next_dev_addr = value;
368 break;
371 case NEXT_DEV_ADDR_EXT: current_table.i2c.next_dev_addr_ext = value;
372 break;
374 case ADDRESS_DELAY: current_table.i2c.address_delay = value;
375 break;
377 #ifndef c6455
378 case SWPLL: current_table.i2c.swPll = value;
379 break;
380 #endif
382 case DEV_ADDR_EXT: if (currentType == SECTION)
383 current_table.i2c.dev_addr_ext = value;
384 else
385 layouts[currentLayout].dev_addr = value;
387 break;
389 case DEV_ADDR: if (currentType == SECTION)
390 current_table.i2c.dev_addr = value;
391 else
392 layouts[currentLayout].address = value;
394 break;
396 case ALIGN: layouts[currentLayout].align = value;
397 break;
400 }
402 } /* assignKeyVal */
405 /*******************************************************************************
406 * FUNCTION PURPOSE: Parse a string input.
407 *******************************************************************************
408 * DESCRIPTION: Takes a string input. Currently only the i2c exe file name can be
409 * assigned a string.
410 *******************************************************************************/
411 void assignKeyStr (int value, char *y)
412 {
413 int i;
414 char *z;
417 /* the input string still contains the quotes. Remove them here */
418 z = &y[1];
419 *strchr (z, '"') = '\0';
421 /* Check if the file name is already open */
422 for (i = 0; i < nProgFiles; i++) {
424 if (!strcmp (z, progFile[i].fname)) {
426 /* Found a match */
428 if (currentType == SECTION) {
430 current_file = i;
432 if (current_table.i2c.dev_addr_ext == 0)
433 current_table.i2c.dev_addr_ext = 0x50; /* hard coded to i2c rom slave address */
435 } else { /* LAYOUT */
437 if (currentLayout < MAX_LAYOUTS)
438 layouts[currentLayout].file[layouts[currentLayout].nFiles++] = i;
439 else
440 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
442 }
445 return;
446 }
448 }
450 /* Open and read the ccs file, set the ROM address */
451 i = openProgFile (z);
452 if (i >= 0) {
454 if (currentType == SECTION) {
456 current_file = i;
457 if (current_table.i2c.dev_addr_ext == 0)
458 current_table.i2c.dev_addr_ext = 0x50;
460 } else { /* LAYOUT */
462 if (currentLayout < MAX_LAYOUTS)
463 layouts[currentLayout].file[layouts[currentLayout].nFiles++] = i;
464 else
465 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
467 }
470 }
472 } /* assignKeyStr */
474 /************************************************************************************
475 * FUNCTION PURPOSE: Put a 32 bit value into the i2c image memory
476 ************************************************************************************
477 * DESCRIPTION: The 32 bit value is placed in memory in big endian format. The
478 * new offset is returned (4 bytes more then the input offset)
479 ************************************************************************************/
480 unsigned int imageWord (unsigned int base, unsigned char *image, unsigned int value)
481 {
482 image[base+0] = (value >> 24) & 0xff;
483 image[base+1] = (value >> 16) & 0xff;
484 image[base+2] = (value >> 8) & 0xff;
485 image[base+3] = (value >> 0) & 0xff;
487 return (base + 4);
489 }
491 /************************************************************************************
492 * FUNCTION PURPOSE: Create a 32 bit value from the image array
493 ************************************************************************************
494 * DESCRIPTION: A 32 bit word in big endian format is created
495 ************************************************************************************/
496 unsigned int formWord (unsigned int p, unsigned char *image)
497 {
498 unsigned int v;
500 v = (image[p+0] << 24) |
501 (image[p+1] << 16) |
502 (image[p+2] << 8) |
503 (image[p+3] << 0) ;
505 return (v);
507 }
509 /************************************************************************************
510 * FUNCTION PURPOSE: Pad the image array
511 ************************************************************************************
512 * DESCRIPTION: Byte (value 0) are added to the image to reach the desired address
513 * The desired address is returned.
514 ************************************************************************************/
515 unsigned int imagePad (unsigned int base, unsigned char *image, unsigned int desired)
516 {
517 int i;
519 if (desired < base) {
520 fprintf (stderr, "romparse: Padd to %d requested, but current base (%d) is already past this point\n",
521 desired, base);
522 exit (-1);
523 }
525 for (i = base; i < desired; i++)
526 image[i] = 0;
528 return (desired);
530 }
532 /************************************************************************************
533 * FUNCTION PURPOSE: Opens and writes the output file
534 ************************************************************************************
535 * DESCRIPTION: Creates the output file in ccs format.
536 ************************************************************************************/
537 void createOutput (void)
538 {
539 FILE *str;
540 int totalLenBytes;
541 int i, j;
542 int nTables, len;
543 unsigned int value, v1, v2;
544 unsigned int base, obase;
545 unsigned char *image;
547 str = fopen ("i2crom.ccs", "w");
548 if (str == NULL) {
549 fprintf (stderr, "romparse: Could not open output file i2crom.ccs for writing\n");
550 exit (-1);
551 }
553 /* Compact the i2c eeprom to use the minimum memory possible */
554 base = PCI_PARAM_BASE;
555 nTables = NUM_BOOT_PARAM_TABLES;
557 if ((compact != 0) && (pciSet == 0)) {
558 nTables = max_index + 1;
559 base = nTables * 0x80; /* The number of parameter tables * size of a parameter table */
560 }
562 if (pciSet)
563 base = base + PCI_EEAI_PARAM_SIZE;
565 /* Layout tables */
566 for (i = 0; i < currentLayout; i++) {
568 /* Determine the size of the table. Four bytes for each file, plus the 4 byte header */
569 v1 = (layouts[i].nFiles * 4) + 4;
571 v2 = (layouts[i].dev_addr << 16) + layouts[i].address;
573 if (v2 == 0)
574 base = base + v1;
576 else {
578 /* Mask out device address bits but extend past 64k */
579 v2 = v2 & I2C_ADDR_MASK;
581 if (base > v2) {
582 fprintf (stderr, "romparse: fatal error - layout block %d specified a start address of 0x%04x\n", i, layouts[i].address);
583 fprintf (stderr, " but this conflicts with the base mapping (ends at 0x%04x)\n", base);
584 exit (-1);
585 }
587 base = layouts[i].address + v1;
589 }
591 }
594 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
595 if (progFile[i].align > 0)
596 base = ((base + progFile[i].align - 1) / progFile[i].align) * progFile[i].align;
597 progFile[i].addressBytes = base;
598 base = base + progFile[i].sizeBytes;
599 }
601 /* Setup the base program file addresses. If a parameter set has
602 * been tagged it means that this is an i2c program load */
603 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
604 for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++) {
605 if (progFile[i].tag[j] >= 0)
606 boot_params[progFile[i].tag[j]].i2c.dev_addr = progFile[i].addressBytes;
607 }
608 }
610 /* Round up the size to a multiple of 4 bytes to fit into a ccs data file */
611 base = (base + 3) & ~3;
614 /* The total length of the i2c eeprom is now stored in base */
615 /* Write out the ccs header */
616 fprintf (str, "1651 1 10000 1 %x\n", base >> 2);
619 /* Create the image in memory */
620 image = malloc (base * sizeof (unsigned char));
621 if (image == NULL) {
622 fprintf (stderr, "romparse: malloc failed creating the output image\n");
623 exit (-1);
624 }
626 /* Write out the boot parameter tables. 0x80 bytes will be written out.
627 * There are 16 bits in every parameter field, which is why the index
628 * is from 0 to 0x40 */
629 base = 0;
630 for (i = 0; i < nTables; i++) {
631 for (j = 0; j < (0x80 >> 1); j += 2) {
632 v1 = boot_params[i].parameter[j];
633 v2 = boot_params[i].parameter[j+1];
634 value = (v1 << 16) | v2;
635 base = imageWord (base, image, value);
636 }
637 }
639 /* Write out the PCI parameter base. If none was included then zeros will be
640 * written out */
641 if (pciSet) {
642 for (i = 0; i < PCI_DATA_LEN_32bit; i++) {
643 base = imageWord (base, image, pciFile.data[i]);
644 }
645 }
648 /* Layout sections */
649 for (i = 0; i < currentLayout; i++) {
651 v1 = (layouts[i].dev_addr << 16) + layouts[i].address;
653 /* Mask out device address bits */
654 v1 = v1 & I2C_ADDR_MASK;
655 if (v1 > 0)
656 base = imagePad (base, image, v1);
657 obase = base;
658 len = (layouts[i].nFiles * 4) + 4;
660 /* Write out the block size and checksum */
661 base = imageWord(base, image, len << 16);
663 for (j = 0; j < layouts[i].nFiles; j++)
664 base = imageWord (base, image, progFile[layouts[i].file[j]].addressBytes);
666 }
669 /* Write out each of the program files */
670 for (i = 0; i < nProgFiles; i++) {
672 base = imagePad (base, image, progFile[i].addressBytes);
674 for (j = 0; j < progFile[i].sizeBytes >> 2; j++)
675 base = imageWord (base, image, (progFile[i]).data[j]);
676 }
678 /* Write out the data file */
679 for (i = 0; i < base; i += 4)
680 fprintf (str, "0x%08x\n", formWord (i, image));
682 free (image);
684 /* Close the output file */
685 fclose (str);
687 } /* createOutput */
689 /************************************************************************************
690 * FUNCTION PURPOSE: Initialize the pci paramter table
691 ************************************************************************************
692 * DESCRIPTION: Zeros the pci parameters
693 ************************************************************************************/
694 void initPciParams (void)
695 {
696 memset (&pciFile, 0, sizeof(pciFile_t));
697 } /* initPciParams */
701 /************************************************************************************
702 * FUNCTION PURPOSE: Parse the input arguments.
703 ************************************************************************************
704 * DESCRIPTION: Returns -1 on invalid args
705 ************************************************************************************/
706 int parseIt (int argc, char *argv[])
707 {
708 int i;
710 if (argc < 2) {
711 fprintf (stderr, "usage: %s [-compact] inputfile\n", argv[0]);
712 return (-1);
713 }
715 inputFile = NULL;
717 for (i = 1; i < argc; ) {
719 if (!strcmp (argv[i], "-compact")) {
720 compact = 1;
721 i += 1;
723 } else {
725 if (inputFile != NULL) {
726 fprintf (stderr, "usage: %s [-compact] inputfile\n", argv[0]);
727 return (-1);
728 }
730 inputFile = argv[i];
731 i += 1;
732 }
733 }
735 return (0);
737 }
741 /************************************************************************************
742 * FUNCTION PURPOSE: main function
743 ************************************************************************************
744 * DESCRIPTION: Performs the processing sequence.
745 ************************************************************************************/
746 int main (int argc, char *argv[])
747 {
748 int i;
750 /* Initialize the tables */
751 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
752 initTable(&boot_params[i]);
754 initTable (¤t_table);
755 current_file = -1;
757 /* Initialize the program file structure */
758 initProgFile ();
760 /* Initialize the PCI param table */
761 initPciParams ();
763 /* Initialize the layout structures */
764 currentLayout = 0;
765 initLayout (&layouts[currentLayout]);
767 /* Parse the input parameters */
768 if (parseIt (argc, argv))
769 return (-1);
772 yyin = fopen (inputFile, "r");
773 if (yyin == NULL) {
774 fprintf (stderr, "%s: could not open file %s\n", argv[0], inputFile);
775 return (-1);
776 }
778 /* Parse the input description file */
779 yyparse();
782 /* Create the output file */
783 createOutput ();
785 return (0);
786 }