a06d70a3fc267e173ac3aff9ee03486172dbde4f
[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   }
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)
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)
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 */
443  
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)
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
483         
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;
492                                
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)
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       }
698         
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 */
716         
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     }
730       
731         
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)
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);
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)
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);
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)
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);
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)
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++)  {
832     
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)  {
900         
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);
918       
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++)  {
969         
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   }
985                                 
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)
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)
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);
1036   
1038 /************************************************************************************
1039  * FUNCTION PURPOSE: Parse the input arguments.
1040  ************************************************************************************
1041  * DESCRIPTION: Returns -1 on invalid args
1042  ************************************************************************************/
1043 int parseIt (int argc, char *argv[])
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);
1086 /************************************************************************************
1087  * FUNCTION PURPOSE: main function
1088  ************************************************************************************
1089  * DESCRIPTION: Performs the processing sequence.
1090  ************************************************************************************/
1091 int main (int argc, char *argv[])
1093   int i;
1095   /* Initialize the tables */
1096   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
1097     initTable(&boot_params[i]);
1099   initTable (&current_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);
1116   
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);