Fixed romparser bug, resolved SDOCM00087159
[keystone-rtos/ibl.git] / src / util / romparse / romparse.c
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)
154   fprintf (stderr, "flex/bison error is %s at line %d\n", s, line);
155 } /* yyerror */
157 void yywrap (void)
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)
168   memset (current_table, 0, sizeof(BOOT_PARAMS_T));
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)
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   }
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)
200     currentType = blockType;
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)
211   cl->nPlt     = 0;
212   cl->dev_addr = i2cRomBase;
213   cl->address  = 0;
214   cl->align    = 0;
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)
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;
247     
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)
262   p->id       = -1;
263   p->address  = 0;
264   p->dev_addr = i2cRomBase;
265   p->len      = 0;
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)
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]);
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)
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
323        
324   current_table.common.checksum = 0;
326   /* Copy the table */
327   memcpy (&boot_params[ctable_index], &current_table, sizeof (BOOT_PARAMS_T));
328   initTable (&current_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)
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)
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 */
444  
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)
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
484         
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;
493                                
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)
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       }
699         
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 */
717         
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     }
731       
732         
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)
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);
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)
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);
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)
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);
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)
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++)  {
833     
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)  {
901         
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);
919       
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++)  {
970         
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   }
986                                 
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)
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)
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);
1037   
1039 /************************************************************************************
1040  * FUNCTION PURPOSE: Parse the input arguments.
1041  ************************************************************************************
1042  * DESCRIPTION: Returns -1 on invalid args
1043  ************************************************************************************/
1044 int parseIt (int argc, char *argv[])
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);
1087 /************************************************************************************
1088  * FUNCTION PURPOSE: main function
1089  ************************************************************************************
1090  * DESCRIPTION: Performs the processing sequence.
1091  ************************************************************************************/
1092 int main (int argc, char *argv[])
1094   int i;
1096   /* Initialize the tables */
1097   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
1098     initTable(&boot_params[i]);
1100   initTable (&current_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);
1117   
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);