]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/util/romparse/romparse.c
0fd8bcfdd78dfc86d9d261149bf7c915dd090d00
[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 = 0x50;
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;
139 /*************************************************************************************
140  * FUNCTION PURPOSE: flex/bison required support functions.
141  *************************************************************************************
142  * DESCRIPTION: yyerror and yywrap are required to support flex and/or bison parsing
143  *              of the parameter description file. yyerror directly reports the
144  *              error, yywrap is unused.
145  *************************************************************************************/
146 void yyerror (char *s)
148   fprintf (stderr, "flex/bison error is %s at line %d\n", s, line);
149 } /* yyerror */
151 void yywrap (void)
153 } /* yywrap */
155 /*************************************************************************************
156  * FUNCTION PURPOSE: Initialize a boot table
157  *************************************************************************************
158  * DESCRIPTION: Sets a boot parameter table to 0s
159  *************************************************************************************/
160 void initTable (BOOT_PARAMS_T *current_table)
162   memset (current_table, 0, sizeof(BOOT_PARAMS_T));
165 /*************************************************************************************
166  * FUNCTION PURPOSE: Initialize the program data file table
167  *************************************************************************************
168  * DESCRIPTION: The size and tags are all setup
169  *************************************************************************************/
170 void initProgFile (void)
172   int i, j;
174   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
175     progFile[i].sizeBytes = 0;
176     progFile[i].align     = 0;
178     for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)
179       progFile[i].tag[j] = -1;
181   }
186 /*************************************************************************************
187  * FUNCTION PURPOSE: Set the currently active parse type
188  *************************************************************************************
189  * DESCRIPTION: Indicates if the subsequent parameters belong to a section or
190  *              a layout
191  *************************************************************************************/
192 void rBegin (int blockType)
194     currentType = blockType;
197 /*************************************************************************************
198  * FUNCTION PURPOSE: Initialize a layout structure
199  *************************************************************************************
200  * DESCRIPTION: The layout is set to the initial state
201  *************************************************************************************/
202 void initLayout (layout_t *cl)
205   cl->nPlt     = 0;
206   cl->dev_addr = i2cRomBase;
207   cl->address  = 0;
208   cl->align    = 0;
212 /*************************************************************************************
213  * FUNCTION PURPOSE: Complete a layout
214  *************************************************************************************
215  * DESCRIPTION: The parser has found a complete layout specification. Complete
216  *              a layout structure
217  *************************************************************************************/
218 void setLayout (void)
220   int i;
221   int currentAlign;
222   int newAlign;
224   for (i = 0; i < layouts[currentLayout].nPlt; i++)  {
226     if (layouts[currentLayout].plt[i].type == PLT_FILE)  {
228       currentAlign = progFile[layouts[currentLayout].plt[i].index].align;
229       newAlign     = layouts[currentLayout].align;
231       if (newAlign > currentAlign)
232         progFile[layouts[currentLayout].plt[i].index].align = newAlign;
233     }
235   }
238   padLayoutOrder[currentPL].type  = LAYOUT;
239   padLayoutOrder[currentPL].index = currentLayout;
240   currentPL += 1;
241     
242   currentLayout += 1;      /* Advance to the next layout */
244   if (currentLayout < MAX_LAYOUTS)
245     initLayout (&layouts[currentLayout]);
247 }    
249 /*************************************************************************************
250  * FUNCTION PURPOSE: Initialize a pad structure
251  *************************************************************************************
252  * DESCRIPTION: A pad structure is set to the default state
253  *************************************************************************************/
254 void initPad (pad_t *p)
256   p->id       = -1;
257   p->address  = 0;
258   p->dev_addr = i2cRomBase;
259   p->len      = 0;
263 /**************************************************************************************
264  * FUNCTION PURPOSE: Complete a pad
265  **************************************************************************************
266  * DESCRIPTION: The parser has found a complete pad specification. Complete the pad
267  *              structure
268  **************************************************************************************/
269 void setPad (void)
272   padLayoutOrder[currentPL].type  = PAD;
273   padLayoutOrder[currentPL].index = currentPad;
274   currentPL += 1;
276   currentPad += 1;
278   if (currentPad < MAX_PADS)
279     initPad (&pads[currentPad]);
284 /*************************************************************************************
285  * FUNCTION PURPOSE: Complete a section
286  *************************************************************************************
287  * DESCRIPTION: The parser has detected a complete section. Copy the section into
288  *              it's correct table location.
289  *************************************************************************************/
290 void section (void)
292   int i;
294   /* It's an error if no section value has been declared */
295   if (ctable_index == -1)  {
296     fprintf (stderr, "romparse: the section did not have a boot paramter index specified\n");
297     exit (-1);
298   }
300   /* Make sure the table is in range */
301   if (ctable_index >= NUM_BOOT_PARAM_TABLES)  {
302     fprintf (stderr, "romparse: The section index is too large (max %d)\n", NUM_BOOT_PARAM_TABLES-1);
303     exit (-1);
304   }
306   /* The length must be set. Currently this program only supports I2C mode, so the
307    * length is fixed */
308   current_table.common.length   = 30;
309   current_table.common.checksum = 0;
311   /* Copy the table */
312   memcpy (&boot_params[ctable_index], &current_table, sizeof (BOOT_PARAMS_T));
313   initTable (&current_table);
315   /* Track the maximum table index */
316   if (ctable_index > max_index)
317     max_index = ctable_index;
319   /* If the section referenced a data file, link the data file back to this section */
320   if (current_file >= 0)  {
321     for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
322       if (progFile[current_file].tag[i] < 0)
323         progFile[current_file].tag[i] = ctable_index;
324         break;
325     }
326   }
328   ctable_index = -1;
329   current_file = -1;
331 } /* section */
333 /***************************************************************************************
334  * FUNCTION PURPOSE: Open a ccs hex file and read in the data.
335  ***************************************************************************************
336  * DESCRIPTION: Reads a ccs hex format data file, loads the file into the
337  *              next program file structure. Returns the index of the just loaded
338  *              table.
339  ***************************************************************************************/
340 int openProgFile (char *fname)
342   FILE *str;
343   int a, b, c, d, e;
344   int i;
345   char iline[132];
347   /* Store the file name */
348   strcpy (progFile[nProgFiles].fname, fname);
350   /* Open the data file */
351   str = fopen (fname, "r");
352   if (str == NULL)  {
353     fprintf (stderr, "romparse: Could not open file %s\n", fname);
354     exit (-1);
355   }
357   /* Read the one line ccs header. The length field in terms of lines */
358   fgets (iline, 132, str);
359   sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
360   progFile[nProgFiles].sizeBytes = e * 4; /* Length was in 4 byte words */
362   /* Read in the data */
363   for (i = 0; i < e; i++)  {
364     fgets (iline, 132, str);
365     sscanf (&(iline[2]), "%x", &((progFile[nProgFiles]).data[i]));
366   }
368   fclose (str);
370   i = nProgFiles;
371   nProgFiles += 1;
373   return (i);
375 } /* openProgFile */
377 /***************************************************************************************
378  * FUNCTION PURPOSE: Load the PCI paramter section
379  ***************************************************************************************
380  * DESCRIPTION: Loads the PCI parameter section and stores it in the rom. */
381 int setPciParams (char *fname)
383   FILE *str;
384   int a, b, c, d, e;
385   int i;
386   char iline[132];
387   char *z;
389   if (pciSet)  {
390     fprintf (stderr, "romparse: PCI parameters specified more then once\n");
391     exit (-1);
392   }
394   /* the input string still contains the quotes. Remove them here */
395   z = &fname[1];
396   *strchr (z, '"') = '\0';
398   /* Store the file name */
399   strcpy (pciFile.fname, z);
401   /* Open the data file */
402   str = fopen (z, "r");
403   if (str == NULL)  {
404     fprintf (stderr, "romparse: Could not open pci file %s\n", fname);
405     exit (-1);
406   }
408   /* The address of the pci params is currently fixed */
409   pciFile.addressBytes = PCI_PARAM_BASE;
411   /* Read the one line ccs header. The length field is in terms of lines */
412   fgets (iline, 132, str);
413   sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
414   pciFile.sizeBytes = e * 4;  /* Convert length to bytes */
416   /* Read in the data */
417   for (i = 0; i < e; i++)  {
418     fgets (iline, 132, str);
419     sscanf (&(iline[2]), "%x", &(pciFile.data[i]));
420   }
422   pciSet = 1;
424   return (0);
426 } /* setPciParams */
428  
430 /***************************************************************************************
431  * FUNCTION PURPOSE: Store an assignment
432  ***************************************************************************************
433  * DESCRIPTION: Stores an assigned value into the current boot parameter table
434  ***************************************************************************************/
435 void assignKeyVal (int field, int value)
438   switch (currentType)   {
441     case SECTION:
444       switch (field)  {
446         case BOOT_MODE:        current_table.common.boot_mode = value;
447                                break;
449         case PARAM_INDEX:      ctable_index = value;
450                                break;
452         case OPTIONS:          current_table.i2c.options = value;
453                                break;
455         case MULTI_I2C_ID:     current_table.i2c.multi_i2c_id = value;
456                                break;
458         case MY_I2C_ID:        current_table.i2c.my_i2c_id = value;
459                                break;
461         case CORE_FREQ_MHZ:    current_table.i2c.core_freq_mhz = value;
462                                break;
464         case I2C_CLK_FREQ_KHZ: current_table.i2c.i2c_clk_freq_khz = value;
465                                break;
467         case NEXT_DEV_ADDR:    current_table.i2c.next_dev_addr = value;
468                                break;
469                                
471         case NEXT_DEV_ADDR_EXT: current_table.i2c.next_dev_addr_ext = value;
472                                 break;
474         case ADDRESS_DELAY:    current_table.i2c.address_delay = value;
475                                break;
477 #if (!defined(c6455) && !defined(c661x))
478         case SWPLL:            current_table.i2c.swPll = value;
479                                break;
480 #endif
482 #ifdef c661x
483         case SWPLL_PREDIV:    current_table.i2c.swPllCfg_lsw &= 0x00ff;
484                               current_table.i2c.swPllCfg_lsw |= ((value & 0xff) << 16);
485                               break;
487         case SWPLL_MULT:      current_table.i2c.swPllCfg_msw &= 0xc000;
488                               current_table.i2c.swPllCfg_msw |= (value & 0x3fff);
489                               break;
491         case SWPLL_POSTDIV:   current_table.i2c.swPllCfg_lsw &= 0xff00;
492                               current_table.i2c.swPllCfg_lsw |= (value & 0xff);
493                               break;
495         case SWPLL_FLAGS:     current_table.i2c.swPllCfg_msw &= 0x3fff;
496                               current_table.i2c.swPllCfg_msw |= ((value & 0x3) << 14);
497                               break;
499 #endif
501         case DEV_ADDR_EXT:     current_table.i2c.dev_addr_ext = value;
502                                break;
504         case DEV_ADDR:         current_table.i2c.dev_addr = value;
505                                break;
508         default:
509             fprintf (stderr, "romparse: Invalid assignment in section specification (line %d)\n", line);
510             break;
512       }
514       break;
517     case LAYOUT:
519       if (currentLayout >= MAX_LAYOUTS)  { 
520         fprintf (stderr, "romparse: Too many layout sections (max = %d)\n", MAX_LAYOUTS);
521         exit (-1);
522       }
525       switch (field)  {
527         case DEV_ADDR_EXT: layouts[currentLayout].dev_addr = value;
528                            break;
530         case DEV_ADDR:     layouts[currentLayout].address = value;
531                            break;
533         case ALIGN:        layouts[currentLayout].align = value;
534                            break;
536         case PAD_FILE_ID:   if (layouts[currentLayout].nPlt >= MAX_LAYOUT_FILES)  {
537                               fprintf (stderr, "romparse: line %d: number of layout entries exceeds maximum of %d\n", line, MAX_LAYOUT_FILES);
538                               exit (-1);
539                             }
540                             layouts[currentLayout].plt[layouts[currentLayout].nPlt].type  = PLT_PAD;
541                             layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = value;
542                             layouts[currentLayout].nPlt += 1;
543                             break;
546         default:
547             fprintf (stderr, "romparase: Invalid assignment in layout specification (line %d)\n", line);
548             break;
550       }
551       break;
554     case PAD:
556       if (currentPad >= MAX_PADS)  {
557         fprintf (stderr, "romparse: Too many pad sections (max = %d)\n", MAX_PADS);
558         exit (-1);
559       }
561       switch (field)  {
563         case DEV_ADDR_EXT: pads[currentPad].dev_addr = value;
564                            break;
566         case DEV_ADDR:  pads[currentPad].address = value;
567                         break;
569         case LENGTH:    pads[currentPad].len = value;
570                         break;
572         case PAD_FILE_ID: pads[currentPad].id = value;
573                           break;
575         default:
576           fprintf (stderr, "romparse: Invalid assignment in pad specificaiton (line %d)\n", line);
577           break;
579       }
580       break;
582    }
585 } /* assignKeyVal */
588 /*******************************************************************************
589  * FUNCTION PURPOSE: Parse a string input.
590  *******************************************************************************
591  * DESCRIPTION: Takes a string input. Currently only the i2c exe file name can be 
592  *              assigned a string. 
593  *******************************************************************************/
594 void assignKeyStr (int value, char *y)
596   int i;
597   char *z;
599   /* The special case of a 0 (plus the quotes) length string means an empty entry for a layout */
600   if (strlen(y) == 2)  {
602     if (currentType == LAYOUT)  {
603       if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES)  {
604         layouts[currentLayout].plt[layouts[currentLayout].nPlt].type  = PLT_FILE;
605         layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = -1;
606         layouts[currentLayout].nPlt += 1;
608       }  else  {
609         fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
610       }
611     }  else
612          fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
614     return;
615   }
618   /* the input string still contains the quotes. Remove them here */
619   z = &y[1];
620   *strchr (z, '"') = '\0';
622   /* Check if the file name is already open */
623   for (i = 0; i < nProgFiles; i++)  {
625     if (!strcmp (z, progFile[i].fname))  {
627       /* Found a match */
629       if (currentType == SECTION)  {
631         current_file = i;
633         if (current_table.i2c.dev_addr_ext == 0)
634           current_table.i2c.dev_addr_ext = i2cRomBase;  /* hard coded to i2c rom slave address */
636       }  else  {   /* LAYOUT */
638         if (currentLayout < MAX_LAYOUTS)  {
639           if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES)  {
640             layouts[currentLayout].plt[layouts[currentLayout].nPlt].type  = PLT_FILE;
641             layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
642             layouts[currentLayout].nPlt += 1;
644           }  else  {
645             fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
646           }
647         }  else
648           fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
650       }
651         
653       return;
654     }
656   }
658   /* Open and read the ccs file, set the ROM address */
659   i = openProgFile (z);
660   if (i >= 0) {
662     if (currentType == SECTION)  {
664       current_file = i;
665       if (current_table.i2c.dev_addr_ext == 0)
666           current_table.i2c.dev_addr_ext = i2cRomBase;
668     }  else  {  /* LAYOUT */
669         
670         if (currentLayout < MAX_LAYOUTS)  {
671           if (layouts[currentLayout].nPlt <= MAX_LAYOUT_FILES)  {
672             layouts[currentLayout].plt[layouts[currentLayout].nPlt].type  = PLT_FILE;
673             layouts[currentLayout].plt[layouts[currentLayout].nPlt].index = i;
674             layouts[currentLayout].nPlt += 1;
676           }  else  {
677             fprintf (stderr, "romparse: line %d: Max number (%d) of layout specification exceeded\n", line, MAX_LAYOUT_FILES);
678           }
679         }  else
680           fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
682     }
683       
684         
685   }
687 } /* assignKeyStr */
689 /************************************************************************************
690  * FUNCTION PURPOSE: Put a 32 bit value into the i2c image memory
691  ************************************************************************************
692  * DESCRIPTION: The 32 bit value is placed in memory in big endian format. The
693  *              new offset is returned (4 bytes more then the input offset)
694  ************************************************************************************/
695 unsigned int imageWord (unsigned int base, unsigned int start, unsigned char *image, unsigned int value)
697     image[base-start+0] = (value >> 24) & 0xff;
698     image[base-start+1] = (value >> 16) & 0xff;
699     image[base-start+2] = (value >>  8) & 0xff;
700     image[base-start+3] = (value >>  0) & 0xff;
702     return (base + 4);
706 /************************************************************************************
707  * FUNCTION PURPOSE: Create a 32 bit value from the image array
708  ************************************************************************************
709  * DESCRIPTION: A 32 bit word in big endian format is created
710  ************************************************************************************/
711 unsigned int formWord (unsigned int p, unsigned char *image)
713   unsigned int v;
715   v = (image[p+0] << 24) |
716       (image[p+1] << 16) |
717       (image[p+2] <<  8) |
718       (image[p+3] <<  0) ;
720   return (v);
724 /************************************************************************************
725  * FUNCTION PURPOSE: Pad the image array
726  ************************************************************************************
727  * DESCRIPTION: Byte (value 0) are added to the image to reach the desired address
728  *              The desired address is returned.
729  ************************************************************************************/
730 unsigned int imagePad (unsigned int base, unsigned int start, unsigned char *image, unsigned int desired)
732   int i;
734   if (desired < base)  {
735     fprintf (stderr, "romparse: Padd to %d requested, but current base (%d) is already past this point\n",
736              desired, base);
737     exit (-1);
738   }
740   for (i = base; i < desired; i++)
741     image[i-start] = 0;
743   return (desired);
747 /************************************************************************************
748  * FUNCTION PURPOSE: Opens and writes the output file
749  ************************************************************************************
750  * DESCRIPTION: Creates the output file in ccs format.
751  ************************************************************************************/
752 void createOutput (void)
754   FILE *str;
755   int   totalLenBytes;
756   int   i, j, k;
757   int   nTables, len;
758   int   i2cRomStart;
759   unsigned int value, v1, v2;
760   unsigned int base;
761   unsigned char *image;
763   str = fopen ("i2crom.ccs", "w");
764   if (str == NULL)  {
765     fprintf (stderr, "romparse: Could not open output file i2crom.ccs for writing\n");
766     exit (-1);
767   }
769   /* Compact the i2c eeprom to use the minimum memory possible */
770   base    = (i2cRomBase << 16) + PCI_PARAM_BASE;
771   nTables = NUM_BOOT_PARAM_TABLES; 
773   if ((compact != 0) && (pciSet == 0))  {
774     nTables = max_index + 1;
775     base    = (i2cRomBase << 16) + (nTables * 0x80);  /* The number of parameter tables * size of a parameter table */
776   }
778   if (pciSet)
779     base = base + PCI_EEAI_PARAM_SIZE;
782   /* Change the layout index value for pad mapping to a true array index value.
783    * Also reflect the device address from the layout into the pad */
784   for (i = 0; i < currentLayout; i++)  {
785     
786     for (j = 0; j < layouts[i].nPlt; j++)  {
788       if (layouts[i].plt[j].type == PLT_PAD)  {
790         for (k = 0; k < currentPad; k++)  {
792           if (layouts[i].plt[j].index == pads[k].id)  {
793             layouts[i].plt[j].index = k;
794             pads[k].dev_addr = layouts[i].dev_addr;
795           }
796         }
797       }
798     }
799   }
801   /* Pad, layout tables */
802   for (i = 0; i < currentPL; i++)  {
804     j = padLayoutOrder[i].index;
806     if (padLayoutOrder[i].type == LAYOUT)  {
808       /* Determine the size of the table. Four bytes for each file, plus the 4 byte header */ 
809       v1 = (layouts[j].nPlt * 4) + 4;
811       v2 = (layouts[j].dev_addr << 16) + layouts[j].address;
813       if (v2 == 0)
814         base = base + v1;
816       else  {
818         if (base > v2)  {
819           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);
820           fprintf (stderr, "          but this conflicts with the base mapping (ends at 0x%04x)\n", base);
821           exit (-1);
822         }
824         base = v2 + v1;  /* new base is the base plus the size */
827       }  
828     }  else  {   /* Otherwise this is a pad */
830       if (base > ((pads[j].dev_addr << 16) + pads[j].address))  {
831         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);
832         fprintf (stderr, "          but this conflicts with the base mapping (ends at 0x%04x)\n", base);
833         exit (-1);
834       }
836       base = (pads[j].dev_addr << 16) + pads[j].address + pads[j].len;
838     }
839   }
841   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
842     if (progFile[i].align > 0)  
843       base = ((base + progFile[i].align - 1) / progFile[i].align) * progFile[i].align;
844     progFile[i].addressBytes = base;
845     base = base + progFile[i].sizeBytes;
846   }
848   /* Setup the base program file addresses. If a parameter set has
849    * been tagged it means that this is an i2c program load */
850   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
851     for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)  {
852       if (progFile[i].tag[j] >= 0)
853         boot_params[progFile[i].tag[j]].i2c.dev_addr = (progFile[i].addressBytes & 0xffff);
854     }
855   }
857   /* Round up the size to a multiple of 4 bytes to fit into a ccs data file */
858   base = (base + 3) & ~3;
860   i2cRomStart = (i2cRomBase << 16);
861       
862   /* The total length of the i2c eeprom is now stored in base */
863   /* Write out the ccs header */
864   fprintf (str, "1651 1 10000 1 %x\n", (base - i2cRomStart) >> 2);
866   /* Create the image in memory */
867   image = malloc ((base - i2cRomStart) * sizeof (unsigned char));
868   if (image == NULL)  {
869     fprintf (stderr, "romparse: malloc failed creating the output image\n");
870     exit (-1);
871   }
873   /* Write out the boot parameter tables. 0x80 bytes will be written out.
874    * There are 16 bits in every parameter field, which is why the index
875    * is from 0 to 0x40 */
876   base = i2cRomBase << 16;
877   for (i = 0; i < nTables; i++)  {
878     for (j = 0; j < (0x80 >> 1); j += 2)  {
879       v1 = boot_params[i].parameter[j];
880       v2 = boot_params[i].parameter[j+1];
881       value = (v1 << 16) | v2;
882       base = imageWord (base, i2cRomStart, image, value);
883     }
884   }
886   /* Write out the PCI parameter base. If none was included then zeros will be
887    * written out */
888   if (pciSet)  {
889     for (i = 0; i < PCI_DATA_LEN_32bit; i++)  {
890       base = imageWord (base, i2cRomStart, image, pciFile.data[i]);
891     }
892   }
895   /* Layout sections */
896   for (i = 0; i < currentLayout; i++)  {
898     v1 = (layouts[i].dev_addr << 16) + layouts[i].address;
900     /* subtract out device address bits */
901     if (v1 > 0)
902       base  = imagePad (base, i2cRomStart, image, v1);
904     len   = (layouts[i].nPlt * 4) + 4;
906     /* Write out the block size and checksum */
907     base = imageWord(base, i2cRomStart, image, len << 16);
909     for (j = 0; j < layouts[i].nPlt; j++)  {
910         
911         if (layouts[i].plt[j].type == PLT_FILE)  {
912           if (layouts[i].plt[j].index == -1)  {
913             base = imageWord (base, i2cRomStart, image, 0xffffffff);
914           } else {
915             base = imageWord (base, i2cRomStart, image, progFile[layouts[i].plt[j].index].addressBytes);
916           } 
917         }  else  {
918           v1 = pads[layouts[i].plt[j].index].dev_addr;
919           v2 = pads[layouts[i].plt[j].index].address;
920           base = imageWord (base, i2cRomStart, image, (v1 << 16) + v2);
921         }
923     }
925   }
926                                 
928   /* Write out each of the program files */
929   for (i = 0; i < nProgFiles; i++)  {
931     v1 = progFile[i].addressBytes;
932     base = imagePad (base, i2cRomStart, image, v1);
934     for (j = 0; j < progFile[i].sizeBytes >> 2; j++)
935       base = imageWord (base, i2cRomStart, image, (progFile[i]).data[j]);
936   }
938   /* Write out the data file */
939   for (i = 0; i < base - i2cRomStart; i += 4) 
940     fprintf (str, "0x%08x\n", formWord (i, image));
942   free (image);
944   /* Close the output file */
945   fclose (str);
947 } /* createOutput  */
949 /************************************************************************************
950  * FUNCTION PURPOSE: Initialize the pci paramter table
951  ************************************************************************************
952  * DESCRIPTION: Zeros the pci parameters
953  ************************************************************************************/
954 void initPciParams (void)
956   memset (&pciFile, 0, sizeof(pciFile_t));
957 } /* initPciParams */
960 /************************************************************************************
961  * FUNCTION PURPOSE: Read an integer value from a string
962  ************************************************************************************
963  * DESCRIPTION: A decimal or hex value is scanned
964  ************************************************************************************/
965 int readVal (char *s)
967   int ret;
969   if ((s[0] == '0') && (s[1] == 'x'))
970     sscanf (&s[2], "%x", &ret);
971   else
972     sscanf (s, "%d", &ret);
974   return (ret);
977   
979 /************************************************************************************
980  * FUNCTION PURPOSE: Parse the input arguments.
981  ************************************************************************************
982  * DESCRIPTION: Returns -1 on invalid args
983  ************************************************************************************/
984 int parseIt (int argc, char *argv[])
986   int i;
988   if (argc < 2)  {
989      fprintf (stderr, "usage: %s [-compact] [-rom_base x] inputfile\n", argv[0]);
990      return (-1);
991   }
993   inputFile = NULL;  
995   for (i = 1; i < argc;  )  {
997     if (!strcmp (argv[i], "-compact"))  {
998       compact = 1;
999       i += 1;
1001     } else if (!strcmp (argv[i], "-rom_base"))  {
1002       i2cRomBase = readVal (argv[i+1]);
1003       i += 2;
1005     } else  {
1007       if (inputFile != NULL)  {
1008         fprintf (stderr, "usage: %s [-compact] inputfile\n", argv[0]);
1009         return (-1);
1010       }
1012       inputFile = argv[i];
1013       i += 1;
1014     }
1015   }
1017   return (0);
1023 /************************************************************************************
1024  * FUNCTION PURPOSE: main function
1025  ************************************************************************************
1026  * DESCRIPTION: Performs the processing sequence.
1027  ************************************************************************************/
1028 int main (int argc, char *argv[])
1030   int i;
1032   /* Initialize the tables */
1033   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
1034     initTable(&boot_params[i]);
1036   initTable (&current_table);
1037   current_file = -1;
1039   /* Initialize the program file structure */
1040   initProgFile ();
1042   /* Initialize the PCI param table */
1043   initPciParams ();
1045   /* Initialize the layout structures */
1046   currentLayout = 0;
1047   initLayout (&layouts[currentLayout]);
1049   /* Parse the input parameters */
1050   if (parseIt (argc, argv))
1051     return (-1);
1053   
1054   yyin = fopen (inputFile, "r");
1055   if (yyin == NULL)  {
1056     fprintf (stderr, "%s: could not open file %s\n", argv[0], inputFile);
1057     return (-1);
1058   }
1060   /* Parse the input description file */
1061   yyparse();
1064   /* Create the output file */
1065   createOutput ();
1067   return (0);