Debugged the IBL two stage load process
[keystone-rtos/ibl.git] / src / util / romparse / romparse.c
1 /*************************************************************************************
2  * FILE PURPOSE: Create an I2C rom with multiple boot parameter sections and
3  *               programs
4  *************************************************************************************
5  * FILE NAME: romparse.c
6  *
7  * DESCRIPTION: Creates a ccs hex file which contains the i2c eprom boot parameter 
8  *              tables as well as any code.
9  *
10  *************************************************************************************/
11 #include <stdio.h>
12 #include <string.h>
13 #include <malloc.h>
14 #include "rparse.tab.h"
15 #include "romparse.h"
17 /*************************************************************************************
18  * Definition: fixed i2c map locations
19  *************************************************************************************/
20 #define PCI_PARAM_BASE  (NUM_BOOT_PARAM_TABLES * 0x80)
21 #define DATA_BASE       (PCI_PARAM_BASE + PCI_EEAI_PARAM_SIZE)
25 /*************************************************************************************
26  * Declaration: The flex input file is assigned based on the command line
27  *************************************************************************************/
28 extern FILE *yyin;
30 /*************************************************************************************
31  * Declaration: Keep track of lines in the parse
32  *************************************************************************************/
33 int line = 1;
35 /*************************************************************************************
36  * Declaration: currentType identifies the current parse mode, either SECTION
37  *              or LAYOUT.
38  *************************************************************************************/
39 int currentType;
41 /*************************************************************************************
42  * Declaration: The boot parameter tables. The current table is copied into position
43  *              when the section parse is complete.
44  *************************************************************************************/
45 BOOT_PARAMS_T boot_params[NUM_BOOT_PARAM_TABLES];
46 BOOT_PARAMS_T current_table;
47 int           current_file;       /* Identifies the program file in the current table */
48 int           ctable_index = -1;  /* Destination of current table */
49 int           max_index    =  0;  /* maximum table index, used for compacting output */
51 /************************************************************************************
52  * Declaration: Layout tables. 
53  ************************************************************************************/
54 layout_t  layouts[MAX_LAYOUTS];   /* Array of layout structures */                
55 int       currentLayout;          /* Currently active layout    */
57 /************************************************************************************
58  * Declaration: Pads
59  ************************************************************************************/
60 pad_t pads[MAX_PADS];             /* Array of pad structures */
61 int   currentPad;                 /* Currently active pad    */
63 /************************************************************************************
64  * Declaration: The structure storing the program data files, and the number of
65  *              programs used.
66  ************************************************************************************/
67 progFile_t progFile[NUM_BOOT_PARAM_TABLES];
68 int        nProgFiles = 0;
70 /************************************************************************************
71  * Declaration: The PCI parameter structure
72  ************************************************************************************/
73 pciFile_t pciFile;
74 int       pciSet = 0;
76 /*************************************************************************************
77  * Declaration: The array that tracks the ordering of pad and layout structures
78  *************************************************************************************/
79 padLayoutOrder_t padLayoutOrder[MAX_PADS+MAX_LAYOUTS];
80 int currentPL = 0;
82 /*************************************************************************************
83  * Declaration: The next free address in the ROM for general data usage. For the
84  *              start address there is room for the initial boot parameter tables, 
85  *              plus room for the PCI eeai config.
86  *************************************************************************************/
87 int romBase = DATA_BASE;
90 /*************************************************************************************
91  * Declaration: Args passed in from the command line
92  *************************************************************************************/
93 char *inputFile;
94 int   compact = 0;
97 /*************************************************************************************
98  * FUNCTION PURPOSE: flex/bison required support functions.
99  *************************************************************************************
100  * DESCRIPTION: yyerror and yywrap are required to support flex and/or bison parsing
101  *              of the parameter description file. yyerror directly reports the
102  *              error, yywrap is unused.
103  *************************************************************************************/
104 void yyerror (char *s)
106   fprintf (stderr, "flex/bison error is %s at line %d\n", s, line);
107 } /* yyerror */
109 void yywrap (void)
111 } /* yywrap */
113 /*************************************************************************************
114  * FUNCTION PURPOSE: Initialize a boot table
115  *************************************************************************************
116  * DESCRIPTION: Sets a boot parameter table to 0s
117  *************************************************************************************/
118 void initTable (BOOT_PARAMS_T *current_table)
120   memset (current_table, 0, sizeof(BOOT_PARAMS_T));
123 /*************************************************************************************
124  * FUNCTION PURPOSE: Initialize the program data file table
125  *************************************************************************************
126  * DESCRIPTION: The size and tags are all setup
127  *************************************************************************************/
128 void initProgFile (void)
130   int i, j;
132   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
133     progFile[i].sizeBytes = 0;
134     progFile[i].align     = 0;
136     for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)
137       progFile[i].tag[j] = -1;
139   }
144 /*************************************************************************************
145  * FUNCTION PURPOSE: Set the currently active parse type
146  *************************************************************************************
147  * DESCRIPTION: Indicates if the subsequent parameters belong to a section or
148  *              a layout
149  *************************************************************************************/
150 void rBegin (int blockType)
152     currentType = blockType;
155 /*************************************************************************************
156  * FUNCTION PURPOSE: Initialize a layout structure
157  *************************************************************************************
158  * DESCRIPTION: The layout is set to the initial state
159  *************************************************************************************/
160 void initLayout (layout_t *cl)
163   cl->nFiles   = 0;
164   cl->dev_addr = 0x50;
165   cl->address  = 0;
166   cl->align    = 0;
170 /*************************************************************************************
171  * FUNCTION PURPOSE: Complete a layout
172  *************************************************************************************
173  * DESCRIPTION: The parser has found a complete layout specification. Complete
174  *              a layout structure
175  *************************************************************************************/
176 void setLayout (void)
178   int i;
179   int currentAlign;
180   int newAlign;
182   for (i = 0; i < layouts[currentLayout].nFiles; i++)  {
183     currentAlign = progFile[layouts[currentLayout].file[i]].align;
184     newAlign     = layouts[currentLayout].align;
186     if (newAlign > currentAlign)
187       progFile[layouts[currentLayout].file[i]].align = newAlign;
189   }
192   padLayoutOrder[currentPL].type  = LAYOUT;
193   padLayoutOrder[currentPL].index = currentLayout;
194   currentPL += 1;
195     
196   currentLayout += 1;      /* Advance to the next layout */
198   if (currentLayout < MAX_LAYOUTS)
199     initLayout (&layouts[currentLayout]);
201 }    
203 /*************************************************************************************
204  * FUNCTION PURPOSE: Initialize a pad structure
205  *************************************************************************************
206  * DESCRIPTION: A pad structure is set to the default state
207  *************************************************************************************/
208 void initPad (pad_t *p)
210   p->address = 0;
211   p->len     = 0;
215 /**************************************************************************************
216  * FUNCTION PURPOSE: Complete a pad
217  **************************************************************************************
218  * DESCRIPTION: The parser has found a complete pad specification. Complete the pad
219  *              structure
220  **************************************************************************************/
221 void setPad (void)
224   padLayoutOrder[currentPL].type  = PAD;
225   padLayoutOrder[currentPL].index = currentPad;
226   currentPL += 1;
228   currentPad += 1;
230   if (currentPad < MAX_PADS)
231     initPad (&pads[currentPad]);
236 /*************************************************************************************
237  * FUNCTION PURPOSE: Complete a section
238  *************************************************************************************
239  * DESCRIPTION: The parser has detected a complete section. Copy the section into
240  *              it's correct table location.
241  *************************************************************************************/
242 void section (void)
244   int i;
246   /* It's an error if no section value has been declared */
247   if (ctable_index == -1)  {
248     fprintf (stderr, "romparse: the section did not have a boot paramter index specified\n");
249     exit (-1);
250   }
252   /* Make sure the table is in range */
253   if (ctable_index >= NUM_BOOT_PARAM_TABLES)  {
254     fprintf (stderr, "romparse: The section index is too large (max %d)\n", NUM_BOOT_PARAM_TABLES-1);
255     exit (-1);
256   }
258   /* The length must be set. Currently this program only supports I2C mode, so the
259    * length is fixed */
260   current_table.common.length   = 30;
261   current_table.common.checksum = 0;
263   /* Copy the table */
264   memcpy (&boot_params[ctable_index], &current_table, sizeof (BOOT_PARAMS_T));
265   initTable (&current_table);
267   /* Track the maximum table index */
268   if (ctable_index > max_index)
269     max_index = ctable_index;
271   /* If the section referenced a data file, link the data file back to this section */
272   if (current_file >= 0)  {
273     for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
274       if (progFile[current_file].tag[i] < 0)
275         progFile[current_file].tag[i] = ctable_index;
276         break;
277     }
278   }
280   ctable_index = -1;
281   current_file = -1;
283 } /* section */
285 /***************************************************************************************
286  * FUNCTION PURPOSE: Open a ccs hex file and read in the data.
287  ***************************************************************************************
288  * DESCRIPTION: Reads a ccs hex format data file, loads the file into the
289  *              next program file structure. Returns the index of the just loaded
290  *              table.
291  ***************************************************************************************/
292 int openProgFile (char *fname)
294   FILE *str;
295   int a, b, c, d, e;
296   int i;
297   char iline[132];
299   /* Store the file name */
300   strcpy (progFile[nProgFiles].fname, fname);
302   /* Open the data file */
303   str = fopen (fname, "r");
304   if (str == NULL)  {
305     fprintf (stderr, "romparse: Could not open file %s\n", fname);
306     exit (-1);
307   }
309   /* Read the one line ccs header. The length field in terms of lines */
310   fgets (iline, 132, str);
311   sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
312   progFile[nProgFiles].sizeBytes = e * 4; /* Length was in 4 byte words */
314   /* Read in the data */
315   for (i = 0; i < e; i++)  {
316     fgets (iline, 132, str);
317     sscanf (&(iline[2]), "%x", &((progFile[nProgFiles]).data[i]));
318   }
320   fclose (str);
322   i = nProgFiles;
323   nProgFiles += 1;
325   return (i);
327 } /* openProgFile */
329 /***************************************************************************************
330  * FUNCTION PURPOSE: Load the PCI paramter section
331  ***************************************************************************************
332  * DESCRIPTION: Loads the PCI parameter section and stores it in the rom. */
333 int setPciParams (char *fname)
335   FILE *str;
336   int a, b, c, d, e;
337   int i;
338   char iline[132];
339   char *z;
341   if (pciSet)  {
342     fprintf (stderr, "romparse: PCI parameters specified more then once\n");
343     exit (-1);
344   }
346   /* the input string still contains the quotes. Remove them here */
347   z = &fname[1];
348   *strchr (z, '"') = '\0';
350   /* Store the file name */
351   strcpy (pciFile.fname, z);
353   /* Open the data file */
354   str = fopen (z, "r");
355   if (str == NULL)  {
356     fprintf (stderr, "romparse: Could not open pci file %s\n", fname);
357     exit (-1);
358   }
360   /* The address of the pci params is currently fixed */
361   pciFile.addressBytes = PCI_PARAM_BASE;
363   /* Read the one line ccs header. The length field is in terms of lines */
364   fgets (iline, 132, str);
365   sscanf (iline, "%x %x %x %x %x", &a, &b, &c, &d, &e);
366   pciFile.sizeBytes = e * 4;  /* Convert length to bytes */
368   /* Read in the data */
369   for (i = 0; i < e; i++)  {
370     fgets (iline, 132, str);
371     sscanf (&(iline[2]), "%x", &(pciFile.data[i]));
372   }
374   pciSet = 1;
376   return (0);
378 } /* setPciParams */
380  
382 /***************************************************************************************
383  * FUNCTION PURPOSE: Store an assignment
384  ***************************************************************************************
385  * DESCRIPTION: Stores an assigned value into the current boot parameter table
386  ***************************************************************************************/
387 void assignKeyVal (int field, int value)
390   switch (currentType)   {
393     case SECTION:
396       switch (field)  {
398         case BOOT_MODE:        current_table.common.boot_mode = value;
399                                break;
401         case PARAM_INDEX:      ctable_index = value;
402                                break;
404         case OPTIONS:          current_table.i2c.options = value;
405                                break;
407         case MULTI_I2C_ID:     current_table.i2c.multi_i2c_id = value;
408                                break;
410         case MY_I2C_ID:        current_table.i2c.my_i2c_id = value;
411                                break;
413         case CORE_FREQ_MHZ:    current_table.i2c.core_freq_mhz = value;
414                                break;
416         case I2C_CLK_FREQ_KHZ: current_table.i2c.i2c_clk_freq_khz = value;
417                                break;
419         case NEXT_DEV_ADDR:    current_table.i2c.next_dev_addr = value;
420                                break;
421                                
423         case NEXT_DEV_ADDR_EXT: current_table.i2c.next_dev_addr_ext = value;
424                                 break;
426         case ADDRESS_DELAY:    current_table.i2c.address_delay = value;
427                                break;
429 #ifndef c6455         
430         case SWPLL:            current_table.i2c.swPll = value;
431                                break;
432 #endif
434         case DEV_ADDR_EXT:     current_table.i2c.dev_addr_ext = value;
435                                break;
437         case DEV_ADDR:         current_table.i2c.dev_addr = value;
438                                break;
441         default:
442             fprintf (stderr, "romparse: Invalid assignment in section specification (line %d)\n", line);
443             break;
445       }
447       break;
450     case LAYOUT:
452       if (currentLayout >= MAX_LAYOUTS)  { 
453         fprintf (stderr, "romparse: Too many layout sections (max = %d)\n", MAX_LAYOUTS);
454         exit (-1);
455       }
458       switch (field)  {
460         case DEV_ADDR_EXT: layouts[currentLayout].dev_addr = value;
461                            break;
463         case DEV_ADDR:     layouts[currentLayout].address = value;
464                            break;
466         case ALIGN:        layouts[currentLayout].align = value;
467                            break;
470         default:
471             fprintf (stderr, "romparase: Invalid assignment in layout specification (line %d)\n", line);
472             break;
474       }
475       break;
478     case PAD:
480       if (currentPad >= MAX_PADS)  {
481         fprintf (stderr, "romparse: Too many pad sections (max = %d)\n", MAX_PADS);
482         exit (-1);
483       }
485       switch (field)  {
487         case DEV_ADDR:  pads[currentPad].address = value;
488                         break;
490         case LENGTH:    pads[currentPad].len = value;
491                         break;
493         default:
494           fprintf (stderr, "romparse: Invalid assignment in pad specificaiton (line %d)\n", line);
495           break;
497       }
498       break;
500    }
503 } /* assignKeyVal */
506 /*******************************************************************************
507  * FUNCTION PURPOSE: Parse a string input.
508  *******************************************************************************
509  * DESCRIPTION: Takes a string input. Currently only the i2c exe file name can be 
510  *              assigned a string. 
511  *******************************************************************************/
512 void assignKeyStr (int value, char *y)
514   int i;
515   char *z;
518   /* the input string still contains the quotes. Remove them here */
519   z = &y[1];
520   *strchr (z, '"') = '\0';
522   /* Check if the file name is already open */
523   for (i = 0; i < nProgFiles; i++)  {
525     if (!strcmp (z, progFile[i].fname))  {
527       /* Found a match */
529       if (currentType == SECTION)  {
531         current_file = i;
533         if (current_table.i2c.dev_addr_ext == 0)
534           current_table.i2c.dev_addr_ext = 0x50;  /* hard coded to i2c rom slave address */
536       }  else  {   /* LAYOUT */
538         if (currentLayout < MAX_LAYOUTS)
539           layouts[currentLayout].file[layouts[currentLayout].nFiles++] = i;
540         else
541           fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
543       }
544         
546       return;
547     }
549   }
551   /* Open and read the ccs file, set the ROM address */
552   i = openProgFile (z);
553   if (i >= 0) {
555     if (currentType == SECTION)  {
557       current_file = i;
558       if (current_table.i2c.dev_addr_ext == 0)
559           current_table.i2c.dev_addr_ext = 0x50;
561     }  else  {  /* LAYOUT */
562         
563         if (currentLayout < MAX_LAYOUTS)
564           layouts[currentLayout].file[layouts[currentLayout].nFiles++] = i;
565         else
566           fprintf (stderr, "romparse: Number of layout sections exceeded (max = %d)\n", MAX_LAYOUTS);
568     }
569       
570         
571   }
573 } /* assignKeyStr */
575 /************************************************************************************
576  * FUNCTION PURPOSE: Put a 32 bit value into the i2c image memory
577  ************************************************************************************
578  * DESCRIPTION: The 32 bit value is placed in memory in big endian format. The
579  *              new offset is returned (4 bytes more then the input offset)
580  ************************************************************************************/
581 unsigned int imageWord (unsigned int base, unsigned char *image, unsigned int value)
583     image[base+0] = (value >> 24) & 0xff;
584     image[base+1] = (value >> 16) & 0xff;
585     image[base+2] = (value >>  8) & 0xff;
586     image[base+3] = (value >>  0) & 0xff;
588     return (base + 4);
592 /************************************************************************************
593  * FUNCTION PURPOSE: Create a 32 bit value from the image array
594  ************************************************************************************
595  * DESCRIPTION: A 32 bit word in big endian format is created
596  ************************************************************************************/
597 unsigned int formWord (unsigned int p, unsigned char *image)
599   unsigned int v;
601   v = (image[p+0] << 24) |
602       (image[p+1] << 16) |
603       (image[p+2] <<  8) |
604       (image[p+3] <<  0) ;
606   return (v);
610 /************************************************************************************
611  * FUNCTION PURPOSE: Pad the image array
612  ************************************************************************************
613  * DESCRIPTION: Byte (value 0) are added to the image to reach the desired address
614  *              The desired address is returned.
615  ************************************************************************************/
616 unsigned int imagePad (unsigned int base, unsigned char *image, unsigned int desired)
618   int i;
620   if (desired < base)  {
621     fprintf (stderr, "romparse: Padd to %d requested, but current base (%d) is already past this point\n",
622              desired, base);
623     exit (-1);
624   }
626   for (i = base; i < desired; i++)
627     image[i] = 0;
629   return (desired);
633 /************************************************************************************
634  * FUNCTION PURPOSE: Opens and writes the output file
635  ************************************************************************************
636  * DESCRIPTION: Creates the output file in ccs format.
637  ************************************************************************************/
638 void createOutput (void)
640   FILE *str;
641   int   totalLenBytes;
642   int   i, j;
643   int   nTables, len;
644   unsigned int value, v1, v2;
645   unsigned int base, obase;
646   unsigned char *image;
648   str = fopen ("i2crom.ccs", "w");
649   if (str == NULL)  {
650     fprintf (stderr, "romparse: Could not open output file i2crom.ccs for writing\n");
651     exit (-1);
652   }
654   /* Compact the i2c eeprom to use the minimum memory possible */
655   base    = PCI_PARAM_BASE;
656   nTables = NUM_BOOT_PARAM_TABLES; 
658   if ((compact != 0) && (pciSet == 0))  {
659     nTables = max_index + 1;
660     base    = nTables * 0x80;  /* The number of parameter tables * size of a parameter table */
661   }
663   if (pciSet)
664     base = base + PCI_EEAI_PARAM_SIZE;
667   /* Pad, layout tables */
668   for (i = 0; i < currentPL; i++)  {
670     j = padLayoutOrder[i].index;
672     if (padLayoutOrder[i].type == LAYOUT)  {
674       /* Determine the size of the table. Four bytes for each file, plus the 4 byte header */ 
675       v1 = (layouts[j].nFiles * 4) + 4;
677       v2 = (layouts[j].dev_addr << 16) + layouts[j].address;
679       if (v2 == 0)
680         base = base + v1;
682       else  {
684         /* Mask out device address bits but extend past 64k */
685         v2 = v2 & I2C_ADDR_MASK;
687         if (base > v2)  {
688           fprintf (stderr, "romparse: fatal error - layout block %d specified a start address of 0x%04x\n", j, layouts[j].address);
689           fprintf (stderr, "          but this conflicts with the base mapping (ends at 0x%04x)\n", base);
690           exit (-1);
691         }
693         base = layouts[j].address + v1;
696       }  
697     }  else  {   /* Otherwise this is a pad */
699       if (base > pads[j].address)  {
700         fprintf (stderr, "romparse: fatal error - pad block %d specified a start address of 0x%04x\n", j, pads[j].address);
701         fprintf (stderr, "          but this conflicts with the base mapping (ends at 0x%04x)\n", base);
702         exit (-1);
703       }
705       base = pads[j].address + pads[j].len;
707     }
708   }
710   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
711     if (progFile[i].align > 0)  
712       base = ((base + progFile[i].align - 1) / progFile[i].align) * progFile[i].align;
713     progFile[i].addressBytes = base + (0x50 << 16);  /* For now hard code the base address */
714     base = base + progFile[i].sizeBytes;
715   }
717   /* Setup the base program file addresses. If a parameter set has
718    * been tagged it means that this is an i2c program load */
719   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)  {
720     for (j = 0; j < NUM_BOOT_PARAM_TABLES; j++)  {
721       if (progFile[i].tag[j] >= 0)
722         boot_params[progFile[i].tag[j]].i2c.dev_addr = (progFile[i].addressBytes & 0xffff);
723     }
724   }
726   /* Round up the size to a multiple of 4 bytes to fit into a ccs data file */
727   base = (base + 3) & ~3;
729       
730   /* The total length of the i2c eeprom is now stored in base */
731   /* Write out the ccs header */
732   fprintf (str, "1651 1 10000 1 %x\n", base >> 2);
735   /* Create the image in memory */
736   image = malloc (base * sizeof (unsigned char));
737   if (image == NULL)  {
738     fprintf (stderr, "romparse: malloc failed creating the output image\n");
739     exit (-1);
740   }
742   /* Write out the boot parameter tables. 0x80 bytes will be written out.
743    * There are 16 bits in every parameter field, which is why the index
744    * is from 0 to 0x40 */
745   base = 0;
746   for (i = 0; i < nTables; i++)  {
747     for (j = 0; j < (0x80 >> 1); j += 2)  {
748       v1 = boot_params[i].parameter[j];
749       v2 = boot_params[i].parameter[j+1];
750       value = (v1 << 16) | v2;
751       base = imageWord (base, image, value);
752     }
753   }
755   /* Write out the PCI parameter base. If none was included then zeros will be
756    * written out */
757   if (pciSet)  {
758     for (i = 0; i < PCI_DATA_LEN_32bit; i++)  {
759       base = imageWord (base, image, pciFile.data[i]);
760     }
761   }
764   /* Layout sections */
765   for (i = 0; i < currentLayout; i++)  {
767     v1 = (layouts[i].dev_addr << 16) + layouts[i].address;
769     /* Mask out device address bits */
770     v1 = v1 & I2C_ADDR_MASK;
771     if (v1 > 0)
772       base  = imagePad (base, image, v1);
773     obase = base;
774     len   = (layouts[i].nFiles * 4) + 4;
776     /* Write out the block size and checksum */
777     base = imageWord(base, image, len << 16);
779     for (j = 0; j < layouts[i].nFiles; j++)
780         base = imageWord (base, image, progFile[layouts[i].file[j]].addressBytes);
782   }
783                                 
785   /* Write out each of the program files */
786   for (i = 0; i < nProgFiles; i++)  {
788     base = imagePad (base, image, (progFile[i].addressBytes & I2C_ADDR_MASK));
790     for (j = 0; j < progFile[i].sizeBytes >> 2; j++)
791       base = imageWord (base, image, (progFile[i]).data[j]);
792   }
794   /* Write out the data file */
795   for (i = 0; i < base; i += 4) 
796     fprintf (str, "0x%08x\n", formWord (i, image));
798   free (image);
800   /* Close the output file */
801   fclose (str);
803 } /* createOutput  */
805 /************************************************************************************
806  * FUNCTION PURPOSE: Initialize the pci paramter table
807  ************************************************************************************
808  * DESCRIPTION: Zeros the pci parameters
809  ************************************************************************************/
810 void initPciParams (void)
812   memset (&pciFile, 0, sizeof(pciFile_t));
813 } /* initPciParams */
817 /************************************************************************************
818  * FUNCTION PURPOSE: Parse the input arguments.
819  ************************************************************************************
820  * DESCRIPTION: Returns -1 on invalid args
821  ************************************************************************************/
822 int parseIt (int argc, char *argv[])
824   int i;
826   if (argc < 2)  {
827      fprintf (stderr, "usage: %s [-compact] inputfile\n", argv[0]);
828      return (-1);
829   }
831   inputFile = NULL;  
833   for (i = 1; i < argc;  )  {
835     if (!strcmp (argv[i], "-compact"))  {
836       compact = 1;
837       i += 1;
839     } else  {
841       if (inputFile != NULL)  {
842         fprintf (stderr, "usage: %s [-compact] inputfile\n", argv[0]);
843         return (-1);
844       }
846       inputFile = argv[i];
847       i += 1;
848     }
849   }
851   return (0);
857 /************************************************************************************
858  * FUNCTION PURPOSE: main function
859  ************************************************************************************
860  * DESCRIPTION: Performs the processing sequence.
861  ************************************************************************************/
862 int main (int argc, char *argv[])
864   int i;
866   /* Initialize the tables */
867   for (i = 0; i < NUM_BOOT_PARAM_TABLES; i++)
868     initTable(&boot_params[i]);
870   initTable (&current_table);
871   current_file = -1;
873   /* Initialize the program file structure */
874   initProgFile ();
876   /* Initialize the PCI param table */
877   initPciParams ();
879   /* Initialize the layout structures */
880   currentLayout = 0;
881   initLayout (&layouts[currentLayout]);
883   /* Parse the input parameters */
884   if (parseIt (argc, argv))
885     return (-1);
887   
888   yyin = fopen (inputFile, "r");
889   if (yyin == NULL)  {
890     fprintf (stderr, "%s: could not open file %s\n", argv[0], inputFile);
891     return (-1);
892   }
894   /* Parse the input description file */
895   yyparse();
898   /* Create the output file */
899   createOutput ();
901   return (0);