Home | History | Annotate | Download | only in UefiVfrCompile
      1 /*++
      2 
      3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   VfrCompiler.cpp
     15 
     16 Abstract:
     17 
     18 --*/
     19 
     20 #include "stdio.h"
     21 #include "string.h"
     22 #include "process.h"
     23 #include "VfrCompiler.h"
     24 
     25 
     26 VOID
     27 CVfrCompiler::SET_RUN_STATUS (
     28   IN COMPILER_RUN_STATUS Status
     29   )
     30 {
     31   mRunStatus = Status;
     32 }
     33 
     34 BOOLEAN
     35 CVfrCompiler::IS_RUN_STATUS (
     36   IN COMPILER_RUN_STATUS Status
     37   )
     38 {
     39   return mRunStatus == Status;
     40 }
     41 
     42 VOID
     43 CVfrCompiler::OptionInitialization (
     44   IN INT32      Argc,
     45   IN INT8       **Argv
     46   )
     47 {
     48   INT32         Index;
     49 
     50   mOptions.VfrFileName[0]                = '\0';
     51   mOptions.RecordListFile[0]             = '\0';
     52   mOptions.CreateRecordListFile          = FALSE;
     53   mOptions.CreateIfrPkgFile              = FALSE;
     54   mOptions.PkgOutputFileName[0]          = '\0';
     55   mOptions.COutputFileName[0]            = '\0';
     56   mOptions.OutputDirectory[0]            = '\0';
     57   mOptions.PreprocessorOutputFileName[0] = '\0';
     58   mOptions.VfrBaseFileName[0]            = '\0';
     59   mOptions.IncludePaths                  = NULL;
     60   mOptions.SkipCPreprocessor             = FALSE;
     61   mOptions.CPreprocessorOptions          = NULL;
     62 
     63   for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {
     64     if ((_stricmp(Argv[Index], "-?") == 0) || (_stricmp(Argv[Index], "-h") == 0)) {
     65       Usage ();
     66       SET_RUN_STATUS (STATUS_DEAD);
     67       return;
     68     } else if (_stricmp(Argv[Index], "-l") == 0) {
     69       mOptions.CreateRecordListFile = TRUE;
     70       gCIfrRecordInfoDB.TurnOn ();
     71     } else if (_stricmp(Argv[Index], "-i") == 0) {
     72       Index++;
     73       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
     74         printf ("%s -i - missing path argument\n", UTILITY_NAME);
     75         goto Fail;
     76       }
     77 
     78       AppendIncludePath(Argv[Index]);
     79     } else if (_stricmp(Argv[Index], "-od") == 0) {
     80       Index++;
     81       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
     82         printf ("%s -od - missing output directory name\n", UTILITY_NAME);
     83         goto Fail;
     84       }
     85       strcpy (mOptions.OutputDirectory, Argv[Index]);
     86       strcat (mOptions.OutputDirectory, "\\");
     87     } else if (_stricmp(Argv[Index], "-ibin") == 0) {
     88       mOptions.CreateIfrPkgFile = TRUE;
     89     } else if (_stricmp(Argv[Index], "-nostrings") == 0) {
     90     } else if (_stricmp(Argv[Index], "-nopp") == 0) {
     91       mOptions.SkipCPreprocessor = TRUE;
     92     } else if (_stricmp(Argv[Index], "-ppflag") == 0) {
     93       Index++;
     94       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
     95         printf ("%s -od - missing C-preprocessor argument\n", UTILITY_NAME);
     96         goto Fail;
     97       }
     98 
     99       AppendCPreprocessorOptions (Argv[Index]);
    100     } else {
    101       printf ("%s unrecognized option %s\n", UTILITY_NAME, Argv[Index]);
    102       Usage ();
    103       goto Fail;
    104     }
    105   }
    106 
    107   if (Index != Argc - 1) {
    108     printf ("%s must specify VFR file name\n", UTILITY_NAME);
    109     Usage ();
    110     goto Fail;
    111   } else {
    112     strcpy (mOptions.VfrFileName, Argv[Index]);
    113   }
    114 
    115   if (SetBaseFileName() != 0) {
    116     goto Fail;
    117   }
    118   if (SetPkgOutputFileName () != 0) {
    119     goto Fail;
    120   }
    121   if (SetCOutputFileName() != 0) {
    122     goto Fail;
    123   }
    124   if (SetPreprocessorOutputFileName () != 0) {
    125     goto Fail;
    126   }
    127   if (SetRecordListFileName () != 0) {
    128     goto Fail;
    129   }
    130   return;
    131 
    132 Fail:
    133   SET_RUN_STATUS (STATUS_FAILED);
    134 
    135   mOptions.VfrFileName[0]                = '\0';
    136   mOptions.RecordListFile[0]             = '\0';
    137   mOptions.CreateRecordListFile          = FALSE;
    138   mOptions.CreateIfrPkgFile              = FALSE;
    139   mOptions.PkgOutputFileName[0]          = '\0';
    140   mOptions.COutputFileName[0]            = '\0';
    141   mOptions.OutputDirectory[0]            = '\0';
    142   mOptions.PreprocessorOutputFileName[0] = '\0';
    143   mOptions.VfrBaseFileName[0]            = '\0';
    144   if (mOptions.IncludePaths != NULL) {
    145     delete mOptions.IncludePaths;
    146     mOptions.IncludePaths                = NULL;
    147   }
    148   if (mOptions.CPreprocessorOptions != NULL) {
    149     delete mOptions.CPreprocessorOptions;
    150     mOptions.CPreprocessorOptions        = NULL;
    151   }
    152 }
    153 
    154 VOID
    155 CVfrCompiler::AppendIncludePath (
    156   IN INT8       *PathStr
    157   )
    158 {
    159   UINT32  Len           = 0;
    160   INT8    *IncludePaths = NULL;
    161 
    162   Len = strlen (" -I ") + strlen (PathStr) + 1;
    163   if (mOptions.IncludePaths != NULL) {
    164     Len += strlen (mOptions.IncludePaths);
    165   }
    166   IncludePaths = new INT8[Len];
    167   if (IncludePaths == NULL) {
    168     printf ("%s memory allocation failure\n", UTILITY_NAME);
    169     return;
    170   }
    171   IncludePaths[0] = '\0';
    172   if (mOptions.IncludePaths != NULL) {
    173     strcat (IncludePaths, mOptions.IncludePaths);
    174   }
    175   strcat (IncludePaths, " -I ");
    176   strcat (IncludePaths, PathStr);
    177   if (mOptions.IncludePaths != NULL) {
    178     delete mOptions.IncludePaths;
    179   }
    180   mOptions.IncludePaths = IncludePaths;
    181 }
    182 
    183 VOID
    184 CVfrCompiler::AppendCPreprocessorOptions (
    185   IN INT8       *Options
    186   )
    187 {
    188   UINT32  Len           = 0;
    189   INT8    *Opt          = NULL;
    190 
    191   Len = strlen (Options) + strlen (" ") + 1;
    192   if (mOptions.CPreprocessorOptions != NULL) {
    193     Len += strlen (mOptions.CPreprocessorOptions);
    194   }
    195   Opt = new INT8[Len];
    196   if (Opt == NULL) {
    197     printf ("%s memory allocation failure\n", UTILITY_NAME);
    198     return;
    199   }
    200   Opt[0] = 0;
    201   if (mOptions.CPreprocessorOptions != NULL) {
    202     strcat (Opt, mOptions.CPreprocessorOptions);
    203   }
    204   strcat (Opt, " ");
    205   strcat (Opt, Options);
    206   if (mOptions.CPreprocessorOptions != NULL) {
    207     delete mOptions.CPreprocessorOptions;
    208   }
    209   mOptions.CPreprocessorOptions = Opt;
    210 }
    211 
    212 INT8
    213 CVfrCompiler::SetBaseFileName (
    214   VOID
    215   )
    216 {
    217   INT8          *pFileName, *pPath, *pExt;
    218 
    219   if (mOptions.VfrFileName[0] == '\0') {
    220     return -1;
    221   }
    222 
    223   pFileName = mOptions.VfrFileName;
    224   while (
    225     ((pPath = strchr (pFileName, '\\')) != NULL) ||
    226     ((pPath = strchr (pFileName, '/')) != NULL)
    227     )
    228   {
    229     pFileName = pPath + 1;
    230   }
    231 
    232   if (pFileName == NULL) {
    233     return -1;
    234   }
    235 
    236   if ((pExt = strchr (pFileName, '.')) == NULL) {
    237     return -1;
    238   }
    239 
    240   strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName);
    241   mOptions.VfrBaseFileName[pExt - pFileName] = '\0';
    242 
    243   return 0;
    244 }
    245 
    246 INT8
    247 CVfrCompiler::SetPkgOutputFileName (
    248   VOID
    249   )
    250 {
    251   if (mOptions.VfrBaseFileName[0] == '\0') {
    252     return -1;
    253   }
    254 
    255   strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);
    256   strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);
    257   strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);
    258 
    259   return 0;
    260 }
    261 
    262 INT8
    263 CVfrCompiler::SetCOutputFileName (
    264   VOID
    265   )
    266 {
    267   if (mOptions.VfrBaseFileName[0] == '\0') {
    268     return -1;
    269   }
    270 
    271   strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);
    272   strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);
    273   strcat (mOptions.COutputFileName, ".c");
    274 
    275   return 0;
    276 }
    277 
    278 INT8
    279 CVfrCompiler::SetPreprocessorOutputFileName (
    280   VOID
    281   )
    282 {
    283   if (mOptions.VfrBaseFileName[0] == '\0') {
    284     return -1;
    285   }
    286 
    287   strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);
    288   strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);
    289   strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
    290 
    291   return 0;
    292 }
    293 
    294 INT8
    295 CVfrCompiler::SetRecordListFileName (
    296   VOID
    297   )
    298 {
    299   if (mOptions.VfrBaseFileName[0] == '\0') {
    300     return -1;
    301   }
    302 
    303   strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);
    304   strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);
    305   strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);
    306 
    307   return 0;
    308 }
    309 
    310 CVfrCompiler::CVfrCompiler (
    311   IN INT32      Argc,
    312   IN INT8       **Argv
    313   )
    314 {
    315   mPreProcessCmd = PREPROCESSOR_COMMAND;
    316   mPreProcessOpt = PREPROCESSOR_OPTIONS;
    317 
    318   OptionInitialization(Argc, Argv);
    319 
    320   if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {
    321     return;
    322   }
    323 
    324   SET_RUN_STATUS(STATUS_INITIALIZED);
    325 }
    326 
    327 CVfrCompiler::~CVfrCompiler (
    328   VOID
    329   )
    330 {
    331   if (mOptions.IncludePaths != NULL) {
    332     delete mOptions.IncludePaths;
    333     mOptions.IncludePaths = NULL;
    334   }
    335 
    336   if (mOptions.CPreprocessorOptions != NULL) {
    337     delete mOptions.CPreprocessorOptions;
    338     mOptions.CPreprocessorOptions = NULL;
    339   }
    340 
    341   SET_RUN_STATUS(STATUS_DEAD);
    342 }
    343 
    344 VOID
    345 CVfrCompiler::Usage (
    346   VOID
    347   )
    348 {
    349   int          Index;
    350   const char   *Str[] = {
    351     UTILITY_NAME" "UTILITY_VERSION" - Intel UEFI VFR Compiler Utility",
    352     "  Copyright (C), 2004 - 2008 Intel Corporation",
    353 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
    354     "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
    355 #endif
    356     "",
    357     "Usage:",
    358     "  "UTILITY_NAME" [OPTION] VFRFILE",
    359     "Description:",
    360     "  Compile VFRFILE.",
    361     "Options:",
    362     "  -? or -h        print this help",
    363     "  -l              create an output IFR listing file",
    364     "  -i IncPath      add IncPath to the search path for VFR included files",
    365     "  -od OutputDir   deposit all output files to directory OutputDir (default=cwd)",
    366     "  -ibin           create an IFR HII pack file",
    367     "  -ppflag CFlags  pass Flags as C-preprocessor-flag",
    368     "  -v or -version  print version information",
    369     NULL
    370   };
    371 
    372   for (Index = 0; Str[Index] != NULL; Index++) {
    373     fprintf (stdout, "%s\n", Str[Index]);
    374   }
    375 }
    376 
    377 
    378 VOID
    379 CVfrCompiler::PreProcess (
    380   VOID
    381   )
    382 {
    383   FILE    *pVfrFile      = NULL;
    384   UINT32  CmdLen         = 0;
    385   INT8    *PreProcessCmd = NULL;
    386 
    387   if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {
    388     goto Fail;
    389   }
    390 
    391   if (mOptions.SkipCPreprocessor == TRUE) {
    392     goto Out;
    393   }
    394 
    395   if ((pVfrFile = fopen (mOptions.VfrFileName, "r")) == NULL) {
    396     printf ("%s could not open input VFR file - %s\n", UTILITY_NAME, mOptions.VfrFileName);
    397     goto Fail;
    398   }
    399   fclose (pVfrFile);
    400 
    401   CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) +
    402   	       strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);
    403   if (mOptions.CPreprocessorOptions != NULL) {
    404     CmdLen += strlen (mOptions.CPreprocessorOptions);
    405   }
    406   if (mOptions.IncludePaths != NULL) {
    407     CmdLen += strlen (mOptions.IncludePaths);
    408   }
    409 
    410   PreProcessCmd = new INT8[CmdLen + 10];
    411   if (PreProcessCmd == NULL) {
    412     printf ("%s could not allocate memory\n", UTILITY_NAME);
    413     goto Fail;
    414   }
    415   strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");
    416   strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");
    417   if (mOptions.IncludePaths != NULL) {
    418     strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");
    419   }
    420   if (mOptions.CPreprocessorOptions != NULL) {
    421     strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");
    422   }
    423   strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");
    424   strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);
    425 
    426   if (system (PreProcessCmd) != 0) {
    427     printf ("%s failed to spawn C preprocessor on VFR file \n\t - %s\n", UTILITY_NAME, PreProcessCmd);
    428     goto Fail;
    429   }
    430 
    431   delete PreProcessCmd;
    432 
    433 Out:
    434   SET_RUN_STATUS (STATUS_PREPROCESSED);
    435   return;
    436 
    437 Fail:
    438   if (!IS_RUN_STATUS(STATUS_DEAD)) {
    439     SET_RUN_STATUS (STATUS_FAILED);
    440   }
    441   delete PreProcessCmd;
    442 }
    443 
    444 extern UINT8 VfrParserStart (IN FILE *);
    445 
    446 VOID
    447 CVfrCompiler::Compile (
    448   VOID
    449   )
    450 {
    451   FILE *pInFile    = NULL;
    452   INT8 *InFileName = NULL;
    453 
    454   if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {
    455     goto Fail;
    456   }
    457 
    458   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
    459 
    460   gCVfrErrorHandle.SetInputFile (InFileName);
    461 
    462   if ((pInFile = fopen (InFileName, "r")) == NULL) {
    463     printf ("%s failed to open input file - %s\n", UTILITY_NAME, InFileName);
    464     goto Fail;
    465   }
    466 
    467   if (VfrParserStart (pInFile) != 0) {
    468     goto Fail;
    469   }
    470 
    471   fclose (pInFile);
    472 
    473   if (gCFormPkg.HavePendingUnassigned () == TRUE) {
    474     gCFormPkg.PendingAssignPrintAll ();
    475     goto Fail;
    476   }
    477 
    478   SET_RUN_STATUS (STATUS_COMPILEED);
    479   return;
    480 
    481 Fail:
    482   if (!IS_RUN_STATUS(STATUS_DEAD)) {
    483     printf ("%s compile error!\n", UTILITY_NAME);
    484     SET_RUN_STATUS (STATUS_FAILED);
    485   }
    486   if (pInFile != NULL) {
    487     fclose (pInFile);
    488   }
    489 }
    490 
    491 VOID
    492 CVfrCompiler::GenBinary (
    493   VOID
    494   )
    495 {
    496   FILE                    *pFile = NULL;
    497 
    498   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
    499     goto Fail;
    500   }
    501 
    502   if (mOptions.CreateIfrPkgFile == TRUE) {
    503     if ((pFile = fopen (mOptions.PkgOutputFileName, "wb")) == NULL) {
    504       printf ("can not open %s\n", mOptions.PkgOutputFileName);
    505       goto Fail;
    506     }
    507     if (gCFormPkg.BuildPkg (pFile) != VFR_RETURN_SUCCESS) {
    508       fclose (pFile);
    509       goto Fail;
    510     }
    511     fclose (pFile);
    512   }
    513 
    514   SET_RUN_STATUS (STATUS_GENBINARY);
    515   return;
    516 
    517 Fail:
    518   if (!IS_RUN_STATUS(STATUS_DEAD)) {
    519     SET_RUN_STATUS (STATUS_FAILED);
    520   }
    521 }
    522 
    523 static const char *gSourceFileHeader[] = {
    524   "//",
    525   "//  DO NOT EDIT -- auto-generated file",
    526   "//",
    527   "//  This file is generated by the vfrcompiler utility",
    528   "//",
    529   NULL
    530 };
    531 
    532 VOID
    533 CVfrCompiler::GenCFile (
    534   VOID
    535   )
    536 {
    537   FILE                    *pFile;
    538   UINT32                  Index;
    539 
    540   if (!IS_RUN_STATUS(STATUS_GENBINARY)) {
    541     goto Fail;
    542   }
    543 
    544   if ((pFile = fopen (mOptions.COutputFileName, "w")) == NULL) {
    545     printf ("failed to open output C file - %s\n", mOptions.COutputFileName);
    546     goto Fail;
    547   }
    548 
    549   for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {
    550     fprintf (pFile, "%s\n", gSourceFileHeader[Index]);
    551   }
    552 
    553   gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);
    554 
    555   if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile) != VFR_RETURN_SUCCESS) {
    556     fclose (pFile);
    557     goto Fail;
    558   }
    559   fclose (pFile);
    560 
    561   SET_RUN_STATUS (STATUS_FINISHED);
    562   return;
    563 
    564 Fail:
    565   if (!IS_RUN_STATUS(STATUS_DEAD)) {
    566     SET_RUN_STATUS (STATUS_FAILED);
    567   }
    568 }
    569 
    570 VOID
    571 CVfrCompiler::GenRecordListFile (
    572   VOID
    573   )
    574 {
    575   INT8   *InFileName = NULL;
    576   FILE   *pInFile    = NULL;
    577   FILE   *pOutFile   = NULL;
    578   INT8   LineBuf[MAX_LINE_LEN];
    579   UINT32 LineNo;
    580 
    581   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
    582 
    583   if (mOptions.CreateRecordListFile == TRUE) {
    584     if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {
    585       return;
    586     }
    587 
    588     if ((pInFile = fopen (InFileName, "r")) == NULL) {
    589       printf ("%s failed to open input VFR preprocessor output file - %s\n", UTILITY_NAME, InFileName);
    590       return;
    591     }
    592 
    593     if ((pOutFile = fopen (mOptions.RecordListFile, "w")) == NULL) {
    594       printf ("%s failed to open record list file for writing - %s\n", UTILITY_NAME, mOptions.RecordListFile);
    595       goto Err1;
    596     }
    597 
    598     fprintf (pOutFile, "//\n//  VFR compiler version " UTILITY_VERSION "\n//\n");
    599     LineNo = 0;
    600     while (!feof (pInFile)) {
    601       if (fgets (LineBuf, MAX_LINE_LEN, pInFile) != NULL) {
    602         fprintf (pOutFile, "%s", LineBuf);
    603         LineNo++;
    604         gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);
    605       }
    606     }
    607 
    608     fclose (pOutFile);
    609     fclose (pInFile);
    610   }
    611 
    612   return;
    613 
    614 Err1:
    615   fclose (pInFile);
    616 }
    617 
    618 INT32
    619 main (
    620   IN INT32             Argc,
    621   IN INT8              **Argv
    622   )
    623 {
    624   COMPILER_RUN_STATUS  Status;
    625   CVfrCompiler         Compiler(Argc, Argv);
    626 
    627   Compiler.PreProcess();
    628   Compiler.Compile();
    629   Compiler.GenBinary();
    630   Compiler.GenCFile();
    631   Compiler.GenRecordListFile ();
    632 
    633   Status = Compiler.RunStatus ();
    634   if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {
    635     return 2;
    636   }
    637 
    638   return 0;
    639 }
    640 
    641