a06d70a3fc267e173ac3aff9ee03486172dbde4f
1 /*
2 *
3 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
38 /*************************************************************************************
39 * FILE PURPOSE: Create an I2C rom with multiple boot parameter sections and
40 * programs
41 *************************************************************************************
42 * FILE NAME: romparse.c
43 *
44 * DESCRIPTION: Creates a ccs hex file which contains the i2c eprom boot parameter
45 * tables as well as any code.
46 *
47 *************************************************************************************/
48 #include <stdio.h>
49 #include <string.h>
50 #include <malloc.h>
51 #include "rparse.tab.h"
52 #include "romparse.h"
54 /*************************************************************************************
55 * Definition: fixed i2c map locations
56 *************************************************************************************/
57 #define PCI_PARAM_BASE (NUM_BOOT_PARAM_TABLES * 0x80)
58 #define DATA_BASE (PCI_PARAM_BASE + PCI_EEAI_PARAM_SIZE)
61 /*************************************************************************************
62 * Declaration: The base address of the i2c ROM being created. This is just
63 * the I2C bus address. The default is 0x50
64 *************************************************************************************/
65 int i2cRomBase = IBL_CFG_I2C_MAP_TABLE_DATA_BUS_ADDR;
67 /*************************************************************************************
68 * Declaration: The flex input file is assigned based on the command line
69 *************************************************************************************/
70 extern FILE *yyin;
72 /*************************************************************************************
73 * Declaration: Keep track of lines in the parse
74 *************************************************************************************/
75 int line = 1;
77 /*************************************************************************************
78 * Declaration: currentType identifies the current parse mode, either SECTION
79 * or LAYOUT.
80 *************************************************************************************/
81 int currentType;
83 /*************************************************************************************
84 * Declaration: The boot parameter tables. The current table is copied into position
85 * when the section parse is complete.
86 *************************************************************************************/
87 BOOT_PARAMS_T boot_params[NUM_BOOT_PARAM_TABLES];
88 BOOT_PARAMS_T current_table;
89 int current_file; /* Identifies the program file in the current table */
90 int ctable_index = -1; /* Destination of current table */
91 int max_index = 0; /* maximum table index, used for compacting output */
93 /************************************************************************************
94 * Declaration: Layout tables.
95 ************************************************************************************/
96 layout_t layouts[MAX_LAYOUTS]; /* Array of layout structures */
97 int currentLayout; /* Currently active layout */
99 /************************************************************************************
100 * Declaration: Pads
101 ************************************************************************************/
102 pad_t pads[MAX_PADS]; /* Array of pad structures */
103 int currentPad; /* Currently active pad */
105 /************************************************************************************
106 * Declaration: The structure storing the program data files, and the number of
107 * programs used.
108 ************************************************************************************/
109 progFile_t progFile[NUM_BOOT_PARAM_TABLES];
110 int nProgFiles = 0;
112 /************************************************************************************
113 * Declaration: The PCI parameter structure
114 ************************************************************************************/
115 pciFile_t pciFile;
116 int pciSet = 0;
118 /*************************************************************************************
119 * Declaration: The array that tracks the ordering of pad and layout structures
120 *************************************************************************************/
121 padLayoutOrder_t padLayoutOrder[MAX_PADS+MAX_LAYOUTS];
122 int currentPL = 0;
124 /*************************************************************************************
125 * Declaration: The next free address in the ROM for general data usage. For the
126 * start address there is room for the initial boot parameter tables,
127 * plus room for the PCI eeai config.
128 *************************************************************************************/
129 int romBase = DATA_BASE;
132 /*************************************************************************************
133 * Declaration: Args passed in from the command line
134 *************************************************************************************/
135 char *inputFile;
136 int compact = 0;
138 /*************************************************************************************
139 * Declaration: The value used to fill gaps in the file. For some devices this
140 * value must be set to 0xff so subsequent writing to these gaps will work
141 *************************************************************************************/
142 unsigned char fillVal = 0;
145 /*************************************************************************************
146 * FUNCTION PURPOSE: flex/bison required support functions.
147 *************************************************************************************
148 * DESCRIPTION: yyerror and yywrap are required to support flex and/or bison parsing
149 * of the parameter description file. yyerror directly reports the
150 * error, yywrap is unused.
151 *************************************************************************************/
152 void yyerror (char *s)
153 {
154 fprintf (stderr, "flex/bison error is %s at line %d\n", s, line);
155 } /* yyerror */
157 void yywrap (void)
158 {
159 } /* yywrap */
161 /*************************************************************************************
162 * FUNCTION PURPOSE: Initialize a boot table
163 *************************************************************************************
164 * DESCRIPTION: Sets a boot parameter table to 0s
165 *************************************************************************************/
166 void initTable (BOOT_PARAMS_T *current_table)
167 {
168 memset (current_table, 0, sizeof(BOOT_PARAMS_T));
169 }
171 /*************************************************************************************
172 * FUNCTION PURPOSE: Initialize the program data file table
173 *************************************************************************************
174 * DESCRIPTION: The size and tags are all setup
175 *************************************************************************************/
176 void initProgFile (void)
177 {
178 int i, j;
180 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
181 progFile[i].sizeBytes = 0;
182 progFile[i].align = 0;
184 for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)
185 progFile[i].tag[j] = -1;
187 }
189 }
192 /*************************************************************************************
193 * FUNCTION PURPOSE: Set the currently active parse type
194 *************************************************************************************
195 * DESCRIPTION: Indicates if the subsequent parameters belong to a section or
196 * a layout
197 *************************************************************************************/
198 void rBegin (int blockType)
199 {
200 currentType = blockType;
201 }
203 /*************************************************************************************
204 * FUNCTION PURPOSE: Initialize a layout structure
205 *************************************************************************************
206 * DESCRIPTION: The layout is set to the initial state
207 *************************************************************************************/
208 void initLayout (layout_t *cl)
209 {
211 cl->nPlt = 0;
212 cl->dev_addr = i2cRomBase;
213 cl->address = 0;
214 cl->align = 0;
216 }
218 /*************************************************************************************
219 * FUNCTION PURPOSE: Complete a layout
220 *************************************************************************************
221 * DESCRIPTION: The parser has found a complete layout specification. Complete
222 * a layout structure
223 *************************************************************************************/
224 void setLayout (void)
225 {
226 int i;
227 int currentAlign;
228 int newAlign;
230 for (i = 0; i < layouts[currentLayout].nPlt; i++) {
232 if (layouts[currentLayout].plt[i].type == PLT_FILE) {
234 currentAlign = progFile[layouts[currentLayout].plt[i].index].align;
235 newAlign = layouts[currentLayout].align;
237 if (newAlign > currentAlign)
238 progFile[layouts[currentLayout].plt[i].index].align = newAlign;
239 }
241 }
244 padLayoutOrder[currentPL].type = LAYOUT;
245 padLayoutOrder[currentPL].index = currentLayout;
246 currentPL += 1;
248 currentLayout += 1; /* Advance to the next layout */
250 if (currentLayout < MAX_LAYOUTS)
251 initLayout (&layouts[currentLayout]);
253 }
255 /*************************************************************************************
256 * FUNCTION PURPOSE: Initialize a pad structure
257 *************************************************************************************
258 * DESCRIPTION: A pad structure is set to the default state
259 *************************************************************************************/
260 void initPad (pad_t *p)
261 {
262 p->id = -1;
263 p->address = 0;
264 p->dev_addr = i2cRomBase;
265 p->len = 0;
266 }
269 /**************************************************************************************
270 * FUNCTION PURPOSE: Complete a pad
271 **************************************************************************************
272 * DESCRIPTION: The parser has found a complete pad specification. Complete the pad
273 * structure
274 **************************************************************************************/
275 void setPad (void)
276 {
278 padLayoutOrder[currentPL].type = PAD;
279 padLayoutOrder[currentPL].index = currentPad;
280 currentPL += 1;
282 currentPad += 1;
284 if (currentPad < MAX_PADS)
285 initPad (&pads[currentPad]);
287 }
290 /*************************************************************************************
291 * FUNCTION PURPOSE: Complete a section
292 *************************************************************************************
293 * DESCRIPTION: The parser has detected a complete section. Copy the section into
294 * it's correct table location.
295 *************************************************************************************/
296 void section (void)
297 {
298 int i;
300 /* It's an error if no section value has been declared */
301 if (ctable_index == -1) {
302 fprintf (stderr, "romparse: the section did not have a boot paramter index specified\n");
303 exit (-1);
304 }
306 /* Make sure the table is in range */
307 if (ctable_index >= NUM_BOOT_PARAM_TABLES) {
308 fprintf (stderr, "romparse: The section index is too large (max %d)\n", NUM_BOOT_PARAM_TABLES-1);
309 exit (-1);
310 }
312 /* The length must be set. Currently this program only supports I2C mode, so the
313 * length is fixed */
315 current_table.common.length = 30;
317 #ifdef c66x
318 if (current_table.common.boot_mode == BOOT_MODE_SPI)
319 current_table.common.length = sizeof(BOOT_PARAMS_SPI_T);
320 else
321 current_table.common.length = sizeof(BOOT_PARAMS_I2C_T);
322 #endif
324 current_table.common.checksum = 0;
326 /* Copy the table */
327 memcpy (&boot_params[ctable_index], ¤t_table, sizeof (BOOT_PARAMS_T));
328 initTable (¤t_table);
330 /* Track the maximum table index */
331 if (ctable_index > max_index)
332 max_index = ctable_index;
334 /* If the section referenced a data file, link the data file back to this section */
335 if (current_file >= 0) {
336 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
337 if (progFile[current_file].tag[i] < 0)
338 progFile[current_file].tag[i] = ctable_index;
339 break;
340 }
341 }
343 ctable_index = -1;
344 current_file = -1;
346 } /* section */
348 /***************************************************************************************
349 * FUNCTION PURPOSE: Open a ccs hex file and read in the data.
350 ***************************************************************************************
351 * DESCRIPTION: Reads a ccs hex format data file, loads the file into the
352 * next program file structure. Returns the index of the just loaded
353 * table.
354 ***************************************************************************************/
355 int openProgFile (char *fname)
356 {
357 FILE *str;
358 int a, b, c, d, e;
359 int i;
360 char iline[132];
362 /* Store the file name */
363 strcpy (progFile[nProgFiles].fname, fname);
365 /* Open the data file */
366 str = fopen (fname, "r");
367 if (str == NULL) {
368 fprintf (stderr, "romparse: Could not open file %s\n", fname);
369 exit (-1);
370 }
372 /* Read the one line ccs header. The length field in terms of lines */
373 fgets (iline, 132, str);
374 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
375 progFile[nProgFiles].sizeBytes = e * 4; /* Length was in 4 byte words */
377 /* Read in the data */
378 for (i = 0; i < e; i++) {
379 fgets (iline, 132, str);
380 sscanf (&(iline[2]), "%x", &((progFile[nProgFiles]).data[i]));
381 }
383 fclose (str);
385 i = nProgFiles;
386 nProgFiles += 1;
388 return (i);
390 } /* openProgFile */
392 /***************************************************************************************
393 * FUNCTION PURPOSE: Load the PCI paramter section
394 ***************************************************************************************
395 * DESCRIPTION: Loads the PCI parameter section and stores it in the rom. */
396 int setPciParams (char *fname)
397 {
398 FILE *str;
399 int a, b, c, d, e;
400 int i;
401 char iline[132];
402 char *z;
404 if (pciSet) {
405 fprintf (stderr, "romparse: PCI parameters specified more then once\n");
406 exit (-1);
407 }
409 /* the input string still contains the quotes. Remove them here */
410 z = &fname[1];
411 *strchr (z, '"') = '\0';
413 /* Store the file name */
414 strcpy (pciFile.fname, z);
416 /* Open the data file */
417 str = fopen (z, "r");
418 if (str == NULL) {
419 fprintf (stderr, "romparse: Could not open pci file %s\n", fname);
420 exit (-1);
421 }
423 /* The address of the pci params is currently fixed */
424 pciFile.addressBytes = PCI_PARAM_BASE;
426 /* Read the one line ccs header. The length field is in terms of lines */
427 fgets (iline, 132, str);
428 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
429 pciFile.sizeBytes = e * 4; /* Convert length to bytes */
431 /* Read in the data */
432 for (i = 0; i < e; i++) {
433 fgets (iline, 132, str);
434 sscanf (&(iline[2]), "%x", &(pciFile.data[i]));
435 }
437 pciSet = 1;
439 return (0);
441 } /* setPciParams */
445 /***************************************************************************************
446 * FUNCTION PURPOSE: Store an assignment
447 ***************************************************************************************
448 * DESCRIPTION: Stores an assigned value into the current boot parameter table
449 ***************************************************************************************/
450 void assignKeyVal (int field, int value)
451 {
453 switch (currentType) {
456 case SECTION:
459 switch (field) {
461 case BOOT_MODE: current_table.common.boot_mode = value;
462 break;
464 case PARAM_INDEX: ctable_index = value;
465 break;
467 case OPTIONS: current_table.i2c.options = value;
468 break;
470 case MULTI_I2C_ID: current_table.i2c.multi_i2c_id = value;
471 break;
473 case MY_I2C_ID: current_table.i2c.my_i2c_id = value;
474 break;
476 case CORE_FREQ_MHZ:
477 #ifdef c66x
478 if (current_table.common.boot_mode == BOOT_MODE_SPI) {
479 current_table.spi.cpuFreqMhz = value;
480 break;
481 }
482 #endif
484 current_table.i2c.core_freq_mhz = value;
485 break;
487 case I2C_CLK_FREQ_KHZ: current_table.i2c.i2c_clk_freq_khz = value;
488 break;
490 case NEXT_DEV_ADDR: current_table.i2c.next_dev_addr = value;
491 break;
494 case NEXT_DEV_ADDR_EXT: current_table.i2c.next_dev_addr_ext = value;
495 break;
497 case ADDRESS_DELAY: current_table.i2c.address_delay = value;
498 break;
500 #if (!defined(c6455) && !defined(c66x))
501 case SWPLL: current_table.i2c.swPll = value;
502 break;
503 #endif
505 #ifdef c66x
506 case SWPLL_PREDIV: current_table.common.swPllCfg_lsw &= 0x00ff;
507 current_table.common.swPllCfg_lsw |= ((value & 0xff) << 16);
508 break;
510 case SWPLL_MULT: current_table.common.swPllCfg_msw &= 0xc000;
511 current_table.common.swPllCfg_msw |= (value & 0x3fff);
512 break;
514 case SWPLL_POSTDIV: current_table.common.swPllCfg_lsw &= 0xff00;
515 current_table.common.swPllCfg_lsw |= (value & 0xff);
516 break;
518 case SWPLL_FLAGS: current_table.common.swPllCfg_msw &= 0x3fff;
519 current_table.common.swPllCfg_msw |= ((value & 0x3) << 14);
520 break;
522 #endif
524 case DEV_ADDR_EXT: current_table.i2c.dev_addr_ext = value;
525 break;
527 case DEV_ADDR: current_table.i2c.dev_addr = value;
528 break;
531 #ifdef c66x
532 case N_PINS: current_table.spi.nPins = value;
533 break;
535 case MODE: current_table.spi.mode = value;
536 break;
538 case C2T_DELAY: current_table.spi.c2tdelay = value;
539 break;
541 case BUS_FREQ_MHZ: current_table.spi.busFreqMhz = value;
542 break;
544 case BUS_FREQ_KHZ: current_table.spi.busFreqKhz = value;
545 break;
547 case ADDR_WIDTH: current_table.spi.addrWidth = value;
548 break;
550 case CSEL: current_table.spi.csel = value;
551 break;
553 #endif
555 default:
556 fprintf (stderr, "romparse: Invalid assignment in section specification (line %d)\n", line);
557 break;
559 }
561 break;
564 case LAYOUT:
566 if (currentLayout >= MAX_LAYOUTS) {
567 fprintf (stderr, "romparse: Too many layout sections (max = %d)\n", MAX_LAYOUTS);
568 exit (-1);
569 }
572 switch (field) {
574 case DEV_ADDR_EXT: layouts[currentLayout].dev_addr = value;
575 break;
577 case DEV_ADDR: layouts[currentLayout].address = value;
578 break;
580 case ALIGN: layouts[currentLayout].align = value;
581 break;
583 case PAD_FILE_ID: if (layouts[currentLayout].nPlt >= MAX_LAYOUT_FILES) {
584 fprintf (stderr, "romparse: line %d: number of layout entries exceeds maximum of %d\n", line, MAX_LAYOUT_FILES);
585 exit (-1);
586 }
587 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_PAD;
588 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = value;
589 layouts[currentLayout].nPlt += 1;
590 break;
593 default:
594 fprintf (stderr, "romparase: Invalid assignment in layout specification (line %d)\n", line);
595 break;
597 }
598 break;
601 case PAD:
603 if (currentPad >= MAX_PADS) {
604 fprintf (stderr, "romparse: Too many pad sections (max = %d)\n", MAX_PADS);
605 exit (-1);
606 }
608 switch (field) {
610 case DEV_ADDR_EXT: pads[currentPad].dev_addr = value;
611 break;
613 case DEV_ADDR: pads[currentPad].address = value;
614 break;
616 case LENGTH: pads[currentPad].len = value;
617 break;
619 case PAD_FILE_ID: pads[currentPad].id = value;
620 break;
622 default:
623 fprintf (stderr, "romparse: Invalid assignment in pad specificaiton (line %d)\n", line);
624 break;
626 }
627 break;
629 }
632 } /* assignKeyVal */
635 /*******************************************************************************
636 * FUNCTION PURPOSE: Parse a string input.
637 *******************************************************************************
638 * DESCRIPTION: Takes a string input. Currently only the i2c exe file name can be
639 * assigned a string.
640 *******************************************************************************/
641 void assignKeyStr (int value, char *y)
642 {
643 int i;
644 char *z;
646 /* The special case of a 0 (plus the quotes) length string means an empty entry for a layout */
647 if (strlen(y) == 2) {
649 if (currentType == LAYOUT) {
650 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
651 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
652 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = -1;
653 layouts[currentLayout].nPlt += 1;
655 } else {
656 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
657 }
658 } else
659 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
661 return;
662 }
665 /* the input string still contains the quotes. Remove them here */
666 z = &y[1];
667 *strchr (z, '"') = '\0';
669 /* Check if the file name is already open */
670 for (i = 0; i < nProgFiles; i++) {
672 if (!strcmp (z, progFile[i].fname)) {
674 /* Found a match */
676 if (currentType == SECTION) {
678 current_file = i;
680 if (current_table.i2c.dev_addr_ext == 0)
681 current_table.i2c.dev_addr_ext = i2cRomBase; /* hard coded to i2c rom slave address */
683 } else { /* LAYOUT */
685 if (currentLayout < MAX_LAYOUTS) {
686 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
687 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
688 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
689 layouts[currentLayout].nPlt += 1;
691 } else {
692 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
693 }
694 } else
695 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
697 }
700 return;
701 }
703 }
705 /* Open and read the ccs file, set the ROM address */
706 i = openProgFile (z);
707 if (i >= 0) {
709 if (currentType == SECTION) {
711 current_file = i;
712 if (current_table.i2c.dev_addr_ext == 0)
713 current_table.i2c.dev_addr_ext = i2cRomBase;
715 } else { /* LAYOUT */
717 if (currentLayout < MAX_LAYOUTS) {
718 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
719 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
720 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
721 layouts[currentLayout].nPlt += 1;
723 } else {
724 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
725 }
726 } else
727 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
729 }
732 }
734 } /* assignKeyStr */
736 /************************************************************************************
737 * FUNCTION PURPOSE: Put a 32 bit value into the i2c image memory
738 ************************************************************************************
739 * DESCRIPTION: The 32 bit value is placed in memory in big endian format. The
740 * new offset is returned (4 bytes more then the input offset)
741 ************************************************************************************/
742 unsigned int imageWord (unsigned int base, unsigned int start, unsigned char *image, unsigned int value)
743 {
744 image[base-start+0] = (value >> 24) & 0xff;
745 image[base-start+1] = (value >> 16) & 0xff;
746 image[base-start+2] = (value >> 8) & 0xff;
747 image[base-start+3] = (value >> 0) & 0xff;
749 return (base + 4);
751 }
753 /************************************************************************************
754 * FUNCTION PURPOSE: Create a 32 bit value from the image array
755 ************************************************************************************
756 * DESCRIPTION: A 32 bit word in big endian format is created
757 ************************************************************************************/
758 unsigned int formWord (unsigned int p, unsigned char *image)
759 {
760 unsigned int v;
762 v = (image[p+0] << 24) |
763 (image[p+1] << 16) |
764 (image[p+2] << 8) |
765 (image[p+3] << 0) ;
767 return (v);
769 }
771 /************************************************************************************
772 * FUNCTION PURPOSE: Pad the image array
773 ************************************************************************************
774 * DESCRIPTION: Byte (value 0) are added to the image to reach the desired address
775 * The desired address is returned.
776 ************************************************************************************/
777 unsigned int imagePad (unsigned int base, unsigned int start, unsigned char *image, unsigned int desired)
778 {
779 int i;
781 if (desired < base) {
782 fprintf (stderr, "romparse: Padd to %d requested, but current base (%d) is already past this point\n",
783 desired, base);
784 exit (-1);
785 }
787 for (i = base; i < desired; i++)
788 image[i-start] = fillVal;
790 return (desired);
792 }
794 /************************************************************************************
795 * FUNCTION PURPOSE: Opens and writes the output file
796 ************************************************************************************
797 * DESCRIPTION: Creates the output file in ccs format.
798 ************************************************************************************/
799 void createOutput (void)
800 {
801 FILE *str;
802 int totalLenBytes;
803 int i, j, k;
804 int nTables, len;
805 int i2cRomStart;
806 unsigned int value, v1, v2;
807 unsigned int base;
808 unsigned char *image;
810 str = fopen ("i2crom.ccs", "w");
811 if (str == NULL) {
812 fprintf (stderr, "romparse: Could not open output file i2crom.ccs for writing\n");
813 exit (-1);
814 }
816 /* Compact the i2c eeprom to use the minimum memory possible */
817 base = (i2cRomBase << 16) + PCI_PARAM_BASE;
818 nTables = NUM_BOOT_PARAM_TABLES;
820 if ((compact != 0) && (pciSet == 0)) {
821 nTables = max_index + 1;
822 base = (i2cRomBase << 16) + (nTables * 0x80); /* The number of parameter tables * size of a parameter table */
823 }
825 if (pciSet)
826 base = base + PCI_EEAI_PARAM_SIZE;
829 /* Change the layout index value for pad mapping to a true array index value.
830 * Also reflect the device address from the layout into the pad */
831 for (i = 0; i < currentLayout; i++) {
833 for (j = 0; j < layouts[i].nPlt; j++) {
835 if (layouts[i].plt[j].type == PLT_PAD) {
837 for (k = 0; k < currentPad; k++) {
839 if (layouts[i].plt[j].index == pads[k].id) {
840 layouts[i].plt[j].index = k;
841 pads[k].dev_addr = layouts[i].dev_addr;
842 }
843 }
844 }
845 }
846 }
848 /* Pad, layout tables */
849 for (i = 0; i < currentPL; i++) {
851 j = padLayoutOrder[i].index;
853 if (padLayoutOrder[i].type == LAYOUT) {
855 /* Determine the size of the table. Four bytes for each file, plus the 4 byte header */
856 v1 = (layouts[j].nPlt * 4) + 4;
858 v2 = (layouts[j].dev_addr << 16) + layouts[j].address;
860 if (v2 == 0)
861 base = base + v1;
863 else {
865 if (base > v2) {
866 fprintf (stderr, "romparse: fatal error - layout block %d specified a start address of 0x%04x\n", j, (layouts[j].dev_addr << 16) + layouts[j].address);
867 fprintf (stderr, " but this conflicts with the base mapping (ends at 0x%04x)\n", base);
868 exit (-1);
869 }
871 base = v2 + v1; /* new base is the base plus the size */
874 }
875 } else { /* Otherwise this is a pad */
877 if (base > ((pads[j].dev_addr << 16) + pads[j].address)) {
878 fprintf (stderr, "romparse: fatal error - pad block %d specified a start address of 0x%04x\n", j, (pads[j].dev_addr << 16) + pads[j].address);
879 fprintf (stderr, " but this conflicts with the base mapping (ends at 0x%04x)\n", base);
880 exit (-1);
881 }
883 base = (pads[j].dev_addr << 16) + pads[j].address + pads[j].len;
885 }
886 }
888 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
889 if (progFile[i].align > 0)
890 base = ((base + progFile[i].align - 1) / progFile[i].align) * progFile[i].align;
891 progFile[i].addressBytes = base;
892 base = base + progFile[i].sizeBytes;
893 }
895 /* Setup the base program file addresses. If a parameter set has
896 * been tagged it means that this is an i2c program load */
897 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
898 for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++) {
899 if (progFile[i].tag[j] >= 0) {
901 #ifdef c66x
902 if (boot_params[progFile[i].tag[j]].common.boot_mode == BOOT_MODE_SPI) {
903 boot_params[progFile[i].tag[j]].spi.read_addr_lsw = (progFile[i].addressBytes & 0xffff);
904 boot_params[progFile[i].tag[j]].spi.read_addr_msw = (progFile[i].addressBytes >> 16) & 0xffff;
905 continue;
906 }
907 #endif
909 boot_params[progFile[i].tag[j]].i2c.dev_addr = (progFile[i].addressBytes & 0xffff);
910 }
911 }
912 }
914 /* Round up the size to a multiple of 4 bytes to fit into a ccs data file */
915 base = (base + 3) & ~3;
917 i2cRomStart = (i2cRomBase << 16);
919 /* The total length of the i2c eeprom is now stored in base */
920 /* Write out the ccs header */
921 fprintf (str, "1651 1 10000 1 %x\n", (base - i2cRomStart) >> 2);
923 /* Create the image in memory */
924 image = malloc ((base - i2cRomStart) * sizeof (unsigned char));
925 if (image == NULL) {
926 fprintf (stderr, "romparse: malloc failed creating the output image\n");
927 exit (-1);
928 }
930 memset (image, fillVal, (base - i2cRomStart));
932 /* Write out the boot parameter tables. 0x80 bytes will be written out.
933 * There are 16 bits in every parameter field, which is why the index
934 * is from 0 to 0x40 */
935 base = i2cRomBase << 16;
936 for (i = 0; i < nTables; i++) {
937 for (j = 0; j < (0x80 >> 1); j += 2) {
938 v1 = boot_params[i].parameter[j];
939 v2 = boot_params[i].parameter[j+1];
940 value = (v1 << 16) | v2;
941 base = imageWord (base, i2cRomStart, image, value);
942 }
943 }
945 /* Write out the PCI parameter base. If none was included then zeros will be
946 * written out */
947 if (pciSet) {
948 for (i = 0; i < PCI_DATA_LEN_32bit; i++) {
949 base = imageWord (base, i2cRomStart, image, pciFile.data[i]);
950 }
951 }
954 /* Layout sections */
955 for (i = 0; i < currentLayout; i++) {
957 v1 = (layouts[i].dev_addr << 16) + layouts[i].address;
959 /* subtract out device address bits */
960 if (v1 > 0)
961 base = imagePad (base, i2cRomStart, image, v1);
963 len = (layouts[i].nPlt * 4) + 4;
965 /* Write out the block size and checksum */
966 base = imageWord(base, i2cRomStart, image, len << 16);
968 for (j = 0; j < layouts[i].nPlt; j++) {
970 if (layouts[i].plt[j].type == PLT_FILE) {
971 if (layouts[i].plt[j].index == -1) {
972 base = imageWord (base, i2cRomStart, image, 0xffffffff);
973 } else {
974 base = imageWord (base, i2cRomStart, image, progFile[layouts[i].plt[j].index].addressBytes);
975 }
976 } else {
977 v1 = pads[layouts[i].plt[j].index].dev_addr;
978 v2 = pads[layouts[i].plt[j].index].address;
979 base = imageWord (base, i2cRomStart, image, (v1 << 16) + v2);
980 }
982 }
984 }
987 /* Write out each of the program files */
988 for (i = 0; i < nProgFiles; i++) {
990 v1 = progFile[i].addressBytes;
991 base = imagePad (base, i2cRomStart, image, v1);
993 for (j = 0; j < progFile[i].sizeBytes >> 2; j++)
994 base = imageWord (base, i2cRomStart, image, (progFile[i]).data[j]);
995 }
997 /* Write out the data file */
998 for (i = 0; i < base - i2cRomStart; i += 4)
999 fprintf (str, "0x%08x\n", formWord (i, image));
1001 free (image);
1003 /* Close the output file */
1004 fclose (str);
1006 } /* createOutput */
1008 /************************************************************************************
1009 * FUNCTION PURPOSE: Initialize the pci paramter table
1010 ************************************************************************************
1011 * DESCRIPTION: Zeros the pci parameters
1012 ************************************************************************************/
1013 void initPciParams (void)
1014 {
1015 memset (&pciFile, 0, sizeof(pciFile_t));
1016 } /* initPciParams */
1019 /************************************************************************************
1020 * FUNCTION PURPOSE: Read an integer value from a string
1021 ************************************************************************************
1022 * DESCRIPTION: A decimal or hex value is scanned
1023 ************************************************************************************/
1024 int readVal (char *s)
1025 {
1026 int ret;
1028 if ((s[0] == '0') && (s[1] == 'x'))
1029 sscanf (&s[2], "%x", &ret);
1030 else
1031 sscanf (s, "%d", &ret);
1033 return (ret);
1035 }
1038 /************************************************************************************
1039 * FUNCTION PURPOSE: Parse the input arguments.
1040 ************************************************************************************
1041 * DESCRIPTION: Returns -1 on invalid args
1042 ************************************************************************************/
1043 int parseIt (int argc, char *argv[])
1044 {
1045 int i;
1047 if (argc < 2) {
1048 fprintf (stderr, "usage: %s [-compact] [-rom_base x] [-fill <fillval>] inputfile\n", argv[0]);
1049 return (-1);
1050 }
1052 inputFile = NULL;
1054 for (i = 1; i < argc; ) {
1056 if (!strcmp (argv[i], "-compact")) {
1057 compact = 1;
1058 i += 1;
1060 } else if (!strcmp (argv[i], "-rom_base")) {
1061 i2cRomBase = readVal (argv[i+1]);
1062 i += 2;
1064 } else if (!strcmp (argv[i], "-fill")) {
1065 fillVal = readVal (argv[i+1]);
1066 i += 2;
1068 } else {
1070 if (inputFile != NULL) {
1071 fprintf (stderr, "usage: %s [-compact] [-rom_base x] [-fill <fillval>] inputfile\n", argv[0]);
1072 return (-1);
1073 }
1075 inputFile = argv[i];
1076 i += 1;
1077 }
1078 }
1080 return (0);
1082 }
1086 /************************************************************************************
1087 * FUNCTION PURPOSE: main function
1088 ************************************************************************************
1089 * DESCRIPTION: Performs the processing sequence.
1090 ************************************************************************************/
1091 int main (int argc, char *argv[])
1092 {
1093 int i;
1095 /* Initialize the tables */
1096 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
1097 initTable(&boot_params[i]);
1099 initTable (¤t_table);
1100 current_file = -1;
1102 /* Initialize the program file structure */
1103 initProgFile ();
1105 /* Initialize the PCI param table */
1106 initPciParams ();
1108 /* Initialize the layout structures */
1109 currentLayout = 0;
1110 initLayout (&layouts[currentLayout]);
1112 /* Parse the input parameters */
1113 if (parseIt (argc, argv))
1114 return (-1);
1117 yyin = fopen (inputFile, "r");
1118 if (yyin == NULL) {
1119 fprintf (stderr, "%s: could not open file %s\n", argv[0], inputFile);
1120 return (-1);
1121 }
1123 /* Parse the input description file */
1124 yyparse();
1127 /* Create the output file */
1128 createOutput ();
1130 return (0);
1131 }