c147d885a3bc9d3e8cebbffcef1de2f94cc0af7b
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 }
342 }
344 ctable_index = -1;
345 current_file = -1;
347 } /* section */
349 /***************************************************************************************
350 * FUNCTION PURPOSE: Open a ccs hex file and read in the data.
351 ***************************************************************************************
352 * DESCRIPTION: Reads a ccs hex format data file, loads the file into the
353 * next program file structure. Returns the index of the just loaded
354 * table.
355 ***************************************************************************************/
356 int openProgFile (char *fname)
357 {
358 FILE *str;
359 int a, b, c, d, e;
360 int i;
361 char iline[132];
363 /* Store the file name */
364 strcpy (progFile[nProgFiles].fname, fname);
366 /* Open the data file */
367 str = fopen (fname, "r");
368 if (str == NULL) {
369 fprintf (stderr, "romparse: Could not open file %s\n", fname);
370 exit (-1);
371 }
373 /* Read the one line ccs header. The length field in terms of lines */
374 fgets (iline, 132, str);
375 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
376 progFile[nProgFiles].sizeBytes = e * 4; /* Length was in 4 byte words */
378 /* Read in the data */
379 for (i = 0; i < e; i++) {
380 fgets (iline, 132, str);
381 sscanf (&(iline[2]), "%x", &((progFile[nProgFiles]).data[i]));
382 }
384 fclose (str);
386 i = nProgFiles;
387 nProgFiles += 1;
389 return (i);
391 } /* openProgFile */
393 /***************************************************************************************
394 * FUNCTION PURPOSE: Load the PCI paramter section
395 ***************************************************************************************
396 * DESCRIPTION: Loads the PCI parameter section and stores it in the rom. */
397 int setPciParams (char *fname)
398 {
399 FILE *str;
400 int a, b, c, d, e;
401 int i;
402 char iline[132];
403 char *z;
405 if (pciSet) {
406 fprintf (stderr, "romparse: PCI parameters specified more then once\n");
407 exit (-1);
408 }
410 /* the input string still contains the quotes. Remove them here */
411 z = &fname[1];
412 *strchr (z, '"') = '\0';
414 /* Store the file name */
415 strcpy (pciFile.fname, z);
417 /* Open the data file */
418 str = fopen (z, "r");
419 if (str == NULL) {
420 fprintf (stderr, "romparse: Could not open pci file %s\n", fname);
421 exit (-1);
422 }
424 /* The address of the pci params is currently fixed */
425 pciFile.addressBytes = PCI_PARAM_BASE;
427 /* Read the one line ccs header. The length field is in terms of lines */
428 fgets (iline, 132, str);
429 sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
430 pciFile.sizeBytes = e * 4; /* Convert length to bytes */
432 /* Read in the data */
433 for (i = 0; i < e; i++) {
434 fgets (iline, 132, str);
435 sscanf (&(iline[2]), "%x", &(pciFile.data[i]));
436 }
438 pciSet = 1;
440 return (0);
442 } /* setPciParams */
446 /***************************************************************************************
447 * FUNCTION PURPOSE: Store an assignment
448 ***************************************************************************************
449 * DESCRIPTION: Stores an assigned value into the current boot parameter table
450 ***************************************************************************************/
451 void assignKeyVal (int field, int value)
452 {
454 switch (currentType) {
457 case SECTION:
460 switch (field) {
462 case BOOT_MODE: current_table.common.boot_mode = value;
463 break;
465 case PARAM_INDEX: ctable_index = value;
466 break;
468 case OPTIONS: current_table.i2c.options = value;
469 break;
471 case MULTI_I2C_ID: current_table.i2c.multi_i2c_id = value;
472 break;
474 case MY_I2C_ID: current_table.i2c.my_i2c_id = value;
475 break;
477 case CORE_FREQ_MHZ:
478 #ifdef c66x
479 if (current_table.common.boot_mode == BOOT_MODE_SPI) {
480 current_table.spi.cpuFreqMhz = value;
481 break;
482 }
483 #endif
485 current_table.i2c.core_freq_mhz = value;
486 break;
488 case I2C_CLK_FREQ_KHZ: current_table.i2c.i2c_clk_freq_khz = value;
489 break;
491 case NEXT_DEV_ADDR: current_table.i2c.next_dev_addr = value;
492 break;
495 case NEXT_DEV_ADDR_EXT: current_table.i2c.next_dev_addr_ext = value;
496 break;
498 case ADDRESS_DELAY: current_table.i2c.address_delay = value;
499 break;
501 #if (!defined(c6455) && !defined(c66x))
502 case SWPLL: current_table.i2c.swPll = value;
503 break;
504 #endif
506 #ifdef c66x
507 case SWPLL_PREDIV: current_table.common.swPllCfg_lsw &= 0x00ff;
508 current_table.common.swPllCfg_lsw |= ((value & 0xff) << 16);
509 break;
511 case SWPLL_MULT: current_table.common.swPllCfg_msw &= 0xc000;
512 current_table.common.swPllCfg_msw |= (value & 0x3fff);
513 break;
515 case SWPLL_POSTDIV: current_table.common.swPllCfg_lsw &= 0xff00;
516 current_table.common.swPllCfg_lsw |= (value & 0xff);
517 break;
519 case SWPLL_FLAGS: current_table.common.swPllCfg_msw &= 0x3fff;
520 current_table.common.swPllCfg_msw |= ((value & 0x3) << 14);
521 break;
523 #endif
525 case DEV_ADDR_EXT: current_table.i2c.dev_addr_ext = value;
526 break;
528 case DEV_ADDR: current_table.i2c.dev_addr = value;
529 break;
532 #ifdef c66x
533 case N_PINS: current_table.spi.nPins = value;
534 break;
536 case MODE: current_table.spi.mode = value;
537 break;
539 case C2T_DELAY: current_table.spi.c2tdelay = value;
540 break;
542 case BUS_FREQ_MHZ: current_table.spi.busFreqMhz = value;
543 break;
545 case BUS_FREQ_KHZ: current_table.spi.busFreqKhz = value;
546 break;
548 case ADDR_WIDTH: current_table.spi.addrWidth = value;
549 break;
551 case CSEL: current_table.spi.csel = value;
552 break;
554 #endif
556 default:
557 fprintf (stderr, "romparse: Invalid assignment in section specification (line %d)\n", line);
558 break;
560 }
562 break;
565 case LAYOUT:
567 if (currentLayout >= MAX_LAYOUTS) {
568 fprintf (stderr, "romparse: Too many layout sections (max = %d)\n", MAX_LAYOUTS);
569 exit (-1);
570 }
573 switch (field) {
575 case DEV_ADDR_EXT: layouts[currentLayout].dev_addr = value;
576 break;
578 case DEV_ADDR: layouts[currentLayout].address = value;
579 break;
581 case ALIGN: layouts[currentLayout].align = value;
582 break;
584 case PAD_FILE_ID: if (layouts[currentLayout].nPlt >= MAX_LAYOUT_FILES) {
585 fprintf (stderr, "romparse: line %d: number of layout entries exceeds maximum of %d\n", line, MAX_LAYOUT_FILES);
586 exit (-1);
587 }
588 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_PAD;
589 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = value;
590 layouts[currentLayout].nPlt += 1;
591 break;
594 default:
595 fprintf (stderr, "romparase: Invalid assignment in layout specification (line %d)\n", line);
596 break;
598 }
599 break;
602 case PAD:
604 if (currentPad >= MAX_PADS) {
605 fprintf (stderr, "romparse: Too many pad sections (max = %d)\n", MAX_PADS);
606 exit (-1);
607 }
609 switch (field) {
611 case DEV_ADDR_EXT: pads[currentPad].dev_addr = value;
612 break;
614 case DEV_ADDR: pads[currentPad].address = value;
615 break;
617 case LENGTH: pads[currentPad].len = value;
618 break;
620 case PAD_FILE_ID: pads[currentPad].id = value;
621 break;
623 default:
624 fprintf (stderr, "romparse: Invalid assignment in pad specificaiton (line %d)\n", line);
625 break;
627 }
628 break;
630 }
633 } /* assignKeyVal */
636 /*******************************************************************************
637 * FUNCTION PURPOSE: Parse a string input.
638 *******************************************************************************
639 * DESCRIPTION: Takes a string input. Currently only the i2c exe file name can be
640 * assigned a string.
641 *******************************************************************************/
642 void assignKeyStr (int value, char *y)
643 {
644 int i;
645 char *z;
647 /* The special case of a 0 (plus the quotes) length string means an empty entry for a layout */
648 if (strlen(y) == 2) {
650 if (currentType == LAYOUT) {
651 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
652 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
653 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = -1;
654 layouts[currentLayout].nPlt += 1;
656 } else {
657 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
658 }
659 } else
660 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
662 return;
663 }
666 /* the input string still contains the quotes. Remove them here */
667 z = &y[1];
668 *strchr (z, '"') = '\0';
670 /* Check if the file name is already open */
671 for (i = 0; i < nProgFiles; i++) {
673 if (!strcmp (z, progFile[i].fname)) {
675 /* Found a match */
677 if (currentType == SECTION) {
679 current_file = i;
681 if (current_table.i2c.dev_addr_ext == 0)
682 current_table.i2c.dev_addr_ext = i2cRomBase; /* hard coded to i2c rom slave address */
684 } else { /* LAYOUT */
686 if (currentLayout < MAX_LAYOUTS) {
687 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
688 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
689 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
690 layouts[currentLayout].nPlt += 1;
692 } else {
693 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
694 }
695 } else
696 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
698 }
701 return;
702 }
704 }
706 /* Open and read the ccs file, set the ROM address */
707 i = openProgFile (z);
708 if (i >= 0) {
710 if (currentType == SECTION) {
712 current_file = i;
713 if (current_table.i2c.dev_addr_ext == 0)
714 current_table.i2c.dev_addr_ext = i2cRomBase;
716 } else { /* LAYOUT */
718 if (currentLayout < MAX_LAYOUTS) {
719 if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES) {
720 layouts[currentLayout].plt[layouts[currentLayout].nPlt].type = PLT_FILE;
721 layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
722 layouts[currentLayout].nPlt += 1;
724 } else {
725 fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
726 }
727 } else
728 fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
730 }
733 }
735 } /* assignKeyStr */
737 /************************************************************************************
738 * FUNCTION PURPOSE: Put a 32 bit value into the i2c image memory
739 ************************************************************************************
740 * DESCRIPTION: The 32 bit value is placed in memory in big endian format. The
741 * new offset is returned (4 bytes more then the input offset)
742 ************************************************************************************/
743 unsigned int imageWord (unsigned int base, unsigned int start, unsigned char *image, unsigned int value)
744 {
745 image[base-start+0] = (value >> 24) & 0xff;
746 image[base-start+1] = (value >> 16) & 0xff;
747 image[base-start+2] = (value >> 8) & 0xff;
748 image[base-start+3] = (value >> 0) & 0xff;
750 return (base + 4);
752 }
754 /************************************************************************************
755 * FUNCTION PURPOSE: Create a 32 bit value from the image array
756 ************************************************************************************
757 * DESCRIPTION: A 32 bit word in big endian format is created
758 ************************************************************************************/
759 unsigned int formWord (unsigned int p, unsigned char *image)
760 {
761 unsigned int v;
763 v = (image[p+0] << 24) |
764 (image[p+1] << 16) |
765 (image[p+2] << 8) |
766 (image[p+3] << 0) ;
768 return (v);
770 }
772 /************************************************************************************
773 * FUNCTION PURPOSE: Pad the image array
774 ************************************************************************************
775 * DESCRIPTION: Byte (value 0) are added to the image to reach the desired address
776 * The desired address is returned.
777 ************************************************************************************/
778 unsigned int imagePad (unsigned int base, unsigned int start, unsigned char *image, unsigned int desired)
779 {
780 int i;
782 if (desired < base) {
783 fprintf (stderr, "romparse: Padd to %d requested, but current base (%d) is already past this point\n",
784 desired, base);
785 exit (-1);
786 }
788 for (i = base; i < desired; i++)
789 image[i-start] = fillVal;
791 return (desired);
793 }
795 /************************************************************************************
796 * FUNCTION PURPOSE: Opens and writes the output file
797 ************************************************************************************
798 * DESCRIPTION: Creates the output file in ccs format.
799 ************************************************************************************/
800 void createOutput (void)
801 {
802 FILE *str;
803 int totalLenBytes;
804 int i, j, k;
805 int nTables, len;
806 int i2cRomStart;
807 unsigned int value, v1, v2;
808 unsigned int base;
809 unsigned char *image;
811 str = fopen ("i2crom.ccs", "w");
812 if (str == NULL) {
813 fprintf (stderr, "romparse: Could not open output file i2crom.ccs for writing\n");
814 exit (-1);
815 }
817 /* Compact the i2c eeprom to use the minimum memory possible */
818 base = (i2cRomBase << 16) + PCI_PARAM_BASE;
819 nTables = NUM_BOOT_PARAM_TABLES;
821 if ((compact != 0) && (pciSet == 0)) {
822 nTables = max_index + 1;
823 base = (i2cRomBase << 16) + (nTables * 0x80); /* The number of parameter tables * size of a parameter table */
824 }
826 if (pciSet)
827 base = base + PCI_EEAI_PARAM_SIZE;
830 /* Change the layout index value for pad mapping to a true array index value.
831 * Also reflect the device address from the layout into the pad */
832 for (i = 0; i < currentLayout; i++) {
834 for (j = 0; j < layouts[i].nPlt; j++) {
836 if (layouts[i].plt[j].type == PLT_PAD) {
838 for (k = 0; k < currentPad; k++) {
840 if (layouts[i].plt[j].index == pads[k].id) {
841 layouts[i].plt[j].index = k;
842 pads[k].dev_addr = layouts[i].dev_addr;
843 }
844 }
845 }
846 }
847 }
849 /* Pad, layout tables */
850 for (i = 0; i < currentPL; i++) {
852 j = padLayoutOrder[i].index;
854 if (padLayoutOrder[i].type == LAYOUT) {
856 /* Determine the size of the table. Four bytes for each file, plus the 4 byte header */
857 v1 = (layouts[j].nPlt * 4) + 4;
859 v2 = (layouts[j].dev_addr << 16) + layouts[j].address;
861 if (v2 == 0)
862 base = base + v1;
864 else {
866 if (base > v2) {
867 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);
868 fprintf (stderr, " but this conflicts with the base mapping (ends at 0x%04x)\n", base);
869 exit (-1);
870 }
872 base = v2 + v1; /* new base is the base plus the size */
875 }
876 } else { /* Otherwise this is a pad */
878 if (base > ((pads[j].dev_addr << 16) + pads[j].address)) {
879 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);
880 fprintf (stderr, " but this conflicts with the base mapping (ends at 0x%04x)\n", base);
881 exit (-1);
882 }
884 base = (pads[j].dev_addr << 16) + pads[j].address + pads[j].len;
886 }
887 }
889 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
890 if (progFile[i].align > 0)
891 base = ((base + progFile[i].align - 1) / progFile[i].align) * progFile[i].align;
892 progFile[i].addressBytes = base;
893 base = base + progFile[i].sizeBytes;
894 }
896 /* Setup the base program file addresses. If a parameter set has
897 * been tagged it means that this is an i2c program load */
898 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++) {
899 for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++) {
900 if (progFile[i].tag[j] >= 0) {
902 #ifdef c66x
903 if (boot_params[progFile[i].tag[j]].common.boot_mode == BOOT_MODE_SPI) {
904 boot_params[progFile[i].tag[j]].spi.read_addr_lsw = (progFile[i].addressBytes & 0xffff);
905 boot_params[progFile[i].tag[j]].spi.read_addr_msw = (progFile[i].addressBytes >> 16) & 0xffff;
906 continue;
907 }
908 #endif
910 boot_params[progFile[i].tag[j]].i2c.dev_addr = (progFile[i].addressBytes & 0xffff);
911 }
912 }
913 }
915 /* Round up the size to a multiple of 4 bytes to fit into a ccs data file */
916 base = (base + 3) & ~3;
918 i2cRomStart = (i2cRomBase << 16);
920 /* The total length of the i2c eeprom is now stored in base */
921 /* Write out the ccs header */
922 fprintf (str, "1651 1 10000 1 %x\n", (base - i2cRomStart) >> 2);
924 /* Create the image in memory */
925 image = malloc ((base - i2cRomStart) * sizeof (unsigned char));
926 if (image == NULL) {
927 fprintf (stderr, "romparse: malloc failed creating the output image\n");
928 exit (-1);
929 }
931 memset (image, fillVal, (base - i2cRomStart));
933 /* Write out the boot parameter tables. 0x80 bytes will be written out.
934 * There are 16 bits in every parameter field, which is why the index
935 * is from 0 to 0x40 */
936 base = i2cRomBase << 16;
937 for (i = 0; i < nTables; i++) {
938 for (j = 0; j < (0x80 >> 1); j += 2) {
939 v1 = boot_params[i].parameter[j];
940 v2 = boot_params[i].parameter[j+1];
941 value = (v1 << 16) | v2;
942 base = imageWord (base, i2cRomStart, image, value);
943 }
944 }
946 /* Write out the PCI parameter base. If none was included then zeros will be
947 * written out */
948 if (pciSet) {
949 for (i = 0; i < PCI_DATA_LEN_32bit; i++) {
950 base = imageWord (base, i2cRomStart, image, pciFile.data[i]);
951 }
952 }
955 /* Layout sections */
956 for (i = 0; i < currentLayout; i++) {
958 v1 = (layouts[i].dev_addr << 16) + layouts[i].address;
960 /* subtract out device address bits */
961 if (v1 > 0)
962 base = imagePad (base, i2cRomStart, image, v1);
964 len = (layouts[i].nPlt * 4) + 4;
966 /* Write out the block size and checksum */
967 base = imageWord(base, i2cRomStart, image, len << 16);
969 for (j = 0; j < layouts[i].nPlt; j++) {
971 if (layouts[i].plt[j].type == PLT_FILE) {
972 if (layouts[i].plt[j].index == -1) {
973 base = imageWord (base, i2cRomStart, image, 0xffffffff);
974 } else {
975 base = imageWord (base, i2cRomStart, image, progFile[layouts[i].plt[j].index].addressBytes);
976 }
977 } else {
978 v1 = pads[layouts[i].plt[j].index].dev_addr;
979 v2 = pads[layouts[i].plt[j].index].address;
980 base = imageWord (base, i2cRomStart, image, (v1 << 16) + v2);
981 }
983 }
985 }
988 /* Write out each of the program files */
989 for (i = 0; i < nProgFiles; i++) {
991 v1 = progFile[i].addressBytes;
992 base = imagePad (base, i2cRomStart, image, v1);
994 for (j = 0; j < progFile[i].sizeBytes >> 2; j++)
995 base = imageWord (base, i2cRomStart, image, (progFile[i]).data[j]);
996 }
998 /* Write out the data file */
999 for (i = 0; i < base - i2cRomStart; i += 4)
1000 fprintf (str, "0x%08x\n", formWord (i, image));
1002 free (image);
1004 /* Close the output file */
1005 fclose (str);
1007 } /* createOutput */
1009 /************************************************************************************
1010 * FUNCTION PURPOSE: Initialize the pci paramter table
1011 ************************************************************************************
1012 * DESCRIPTION: Zeros the pci parameters
1013 ************************************************************************************/
1014 void initPciParams (void)
1015 {
1016 memset (&pciFile, 0, sizeof(pciFile_t));
1017 } /* initPciParams */
1020 /************************************************************************************
1021 * FUNCTION PURPOSE: Read an integer value from a string
1022 ************************************************************************************
1023 * DESCRIPTION: A decimal or hex value is scanned
1024 ************************************************************************************/
1025 int readVal (char *s)
1026 {
1027 int ret;
1029 if ((s[0] == '0') && (s[1] == 'x'))
1030 sscanf (&s[2], "%x", &ret);
1031 else
1032 sscanf (s, "%d", &ret);
1034 return (ret);
1036 }
1039 /************************************************************************************
1040 * FUNCTION PURPOSE: Parse the input arguments.
1041 ************************************************************************************
1042 * DESCRIPTION: Returns -1 on invalid args
1043 ************************************************************************************/
1044 int parseIt (int argc, char *argv[])
1045 {
1046 int i;
1048 if (argc < 2) {
1049 fprintf (stderr, "usage: %s [-compact] [-rom_base x] [-fill <fillval>] inputfile\n", argv[0]);
1050 return (-1);
1051 }
1053 inputFile = NULL;
1055 for (i = 1; i < argc; ) {
1057 if (!strcmp (argv[i], "-compact")) {
1058 compact = 1;
1059 i += 1;
1061 } else if (!strcmp (argv[i], "-rom_base")) {
1062 i2cRomBase = readVal (argv[i+1]);
1063 i += 2;
1065 } else if (!strcmp (argv[i], "-fill")) {
1066 fillVal = readVal (argv[i+1]);
1067 i += 2;
1069 } else {
1071 if (inputFile != NULL) {
1072 fprintf (stderr, "usage: %s [-compact] [-rom_base x] [-fill <fillval>] inputfile\n", argv[0]);
1073 return (-1);
1074 }
1076 inputFile = argv[i];
1077 i += 1;
1078 }
1079 }
1081 return (0);
1083 }
1087 /************************************************************************************
1088 * FUNCTION PURPOSE: main function
1089 ************************************************************************************
1090 * DESCRIPTION: Performs the processing sequence.
1091 ************************************************************************************/
1092 int main (int argc, char *argv[])
1093 {
1094 int i;
1096 /* Initialize the tables */
1097 for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
1098 initTable(&boot_params[i]);
1100 initTable (¤t_table);
1101 current_file = -1;
1103 /* Initialize the program file structure */
1104 initProgFile ();
1106 /* Initialize the PCI param table */
1107 initPciParams ();
1109 /* Initialize the layout structures */
1110 currentLayout = 0;
1111 initLayout (&layouts[currentLayout]);
1113 /* Parse the input parameters */
1114 if (parseIt (argc, argv))
1115 return (-1);
1118 yyin = fopen (inputFile, "r");
1119 if (yyin == NULL) {
1120 fprintf (stderr, "%s: could not open file %s\n", argv[0], inputFile);
1121 return (-1);
1122 }
1124 /* Parse the input description file */
1125 yyparse();
1128 /* Create the output file */
1129 createOutput ();
1131 return (0);
1132 }