Home | History | Annotate | Download | only in GenAprioriFile
      1 /*++
      2 
      3  Copyright (c) 2006 - 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 
     13 Module Name:
     14 
     15   GenAprioriFile.c
     16 
     17 Abstract:
     18 
     19   Given an input file containing a list of GUIDs (or Guided file names),
     20   convert the file to an Apriori file consumable by the dispatcher.
     21 
     22 --*/
     23 
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <ctype.h>
     27 
     28 #include "EfiCommon.h"
     29 #include "ParseInf.h"
     30 #include "CommonLib.h"  // for compare guid
     31 #include "EfiUtilityMsgs.h"
     32 
     33 #define MAX_LINE_LEN  200
     34 #define MAX_PATH      200
     35 
     36 //
     37 // typedef unsigned int          STATUS;
     38 // #define STATUS_SUCCESS        0
     39 // #define STATUS_WARNING        1
     40 // #define STATUS_ERROR          2
     41 //
     42 #define UTILITY_NAME    "GenAprioriFile"
     43 #define UTILITY_VERSION "v1.0"
     44 //
     45 // Here's all our globals.
     46 //
     47 static struct {
     48   FILE    *BinFptr; // output dependencies to this file
     49   INT8    *AprioriFileName;
     50   INT8    *OutputFileName;
     51   BOOLEAN Intelligent;
     52   BOOLEAN Verbose;
     53   BOOLEAN NullTerminate;
     54 } mGlobals;
     55 
     56 static
     57 STATUS
     58 ProcessArgs (
     59   int   Argc,
     60   char  *Argv[]
     61   );
     62 
     63 static
     64 BOOLEAN
     65 IsCommentLine (
     66   INT8    *Line
     67   );
     68 
     69 static
     70 void
     71 Usage (
     72   VOID
     73   );
     74 
     75 int
     76 main (
     77   int   Argc,
     78   char  *Argv[]
     79   )
     80 /*++
     81 
     82 Routine Description:
     83 
     84   Call the routine to parse the command-line options, then process the
     85   Apriori list file and generate the GUID file.
     86 
     87 Arguments:
     88 
     89   Standard C main() argc and argv.
     90 
     91 Returns:
     92 
     93   0       if successful
     94   nonzero otherwise
     95 
     96 --*/
     97 // GC_TODO:    Argc - add argument and description to function comment
     98 // GC_TODO:    ] - add argument and description to function comment
     99 {
    100   STATUS    Status;
    101   FILE      *AprioriFptr;
    102   FILE      *BinFptr;
    103   INT8      Line[MAX_LINE_LEN];
    104   EFI_GUID  Guid;
    105   EFI_GUID  GuidIn;
    106   EFI_GUID  ZeroGuid;
    107   UINT32    LineCounter;
    108   //
    109   // Initialize the error printing routines
    110   //
    111   SetUtilityName (UTILITY_NAME);
    112   //
    113   // Clear our globals
    114   //
    115   memset ((char *) &mGlobals, 0, sizeof (mGlobals));
    116   memset ((char *) &ZeroGuid, 0, sizeof (ZeroGuid));
    117   AprioriFptr = NULL;
    118   BinFptr     = NULL;
    119 
    120   //
    121   // Process the command-line arguments
    122   //
    123   Status = ProcessArgs (Argc, Argv);
    124   if (Status != STATUS_SUCCESS) {
    125     return Status;
    126   }
    127   //
    128   // If arguments were ok, then open the Apriori file and process it.
    129   //
    130   if ((AprioriFptr = fopen (mGlobals.AprioriFileName, "r")) == NULL) {
    131     Error (NULL, 0, 0, mGlobals.AprioriFileName, "failed to open file for reading");
    132     goto FinishUp;
    133   }
    134   //
    135   // If -i intelligent option specified, then attempt to read and
    136   // existing output file and see if we'd be creating an identical file.
    137   //
    138   if (mGlobals.Intelligent) {
    139     if ((BinFptr = fopen (mGlobals.OutputFileName, "rb")) == NULL) {
    140       if (mGlobals.Verbose) {
    141         DebugMsg (NULL, 0, 0, "Creating new apriori file -- no existing file", NULL);
    142       }
    143 
    144       goto CreateFile;
    145     }
    146     //
    147     // Read lines from the input file until done. Convert each to a guid, then
    148     // read a guid from the input file and compare them.
    149     //
    150     while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) {
    151 
    152       if (IsCommentLine (Line)) {
    153         continue;
    154       }
    155       //
    156       // Convert to a guid
    157       //
    158       if (StringToGuid (Line, &Guid) != EFI_SUCCESS) {
    159         if (mGlobals.Verbose) {
    160           DebugMsg (NULL, 0, 0, "failed to read GUID from input text file -- creating new file", NULL);
    161         }
    162 
    163         goto CreateFile;
    164       }
    165       //
    166       // Read guid from input file, then compare
    167       //
    168       if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) {
    169         if (mGlobals.Verbose) {
    170           DebugMsg (NULL, 0, 0, "failed to read GUID from input binary file -- creating new file", NULL);
    171         }
    172 
    173         goto CreateFile;
    174       }
    175 
    176       if (CompareGuid (&Guid, &GuidIn) != 0) {
    177         if (mGlobals.Verbose) {
    178           DebugMsg (NULL, 0, 0, "GUID comparison failed -- creating new file", NULL);
    179         }
    180 
    181         goto CreateFile;
    182       }
    183     }
    184     //
    185     // May be one more NULL guid in the binary file
    186     //
    187     if (mGlobals.NullTerminate) {
    188       if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) {
    189         if (mGlobals.Verbose) {
    190           DebugMsg (NULL, 0, 0, "failed to read NULL GUID from input binary file -- creating new file", NULL);
    191         }
    192 
    193         goto CreateFile;
    194       }
    195 
    196       if (CompareGuid (&GuidIn, &ZeroGuid) != 0) {
    197         if (mGlobals.Verbose) {
    198           DebugMsg (NULL, 0, 0, "NULL GUID comparison failed -- creating new file", NULL);
    199         }
    200 
    201         goto CreateFile;
    202       }
    203     }
    204     //
    205     // Make sure we're at the end of both files.
    206     //
    207     if ((fgets (Line, sizeof (Line), AprioriFptr) != NULL) || (fread (&GuidIn, 1, 1, BinFptr) != 0)) {
    208       if (mGlobals.Verbose) {
    209         DebugMsg (NULL, 0, 0, "file sizes different, -i test failed -- creating new file", NULL);
    210       }
    211 
    212       goto CreateFile;
    213     }
    214 
    215     if (mGlobals.Verbose) {
    216       DebugMsg (NULL, 0, 0, "existing file would be unchanged -- keeping existing apriori file", NULL);
    217     }
    218 
    219     goto FinishUp;
    220   }
    221 
    222 CreateFile:
    223   //
    224   // Rewind the Apriori file in case -i was specified. Also
    225   // try to close the output file for the case where we prescanned
    226   // it (again, because of -i).
    227   //
    228   rewind (AprioriFptr);
    229   if (BinFptr != NULL) {
    230     fclose (BinFptr);
    231   }
    232   //
    233   // Open the output file
    234   //
    235   if ((BinFptr = fopen (mGlobals.OutputFileName, "wb")) == NULL) {
    236     Error (NULL, 0, 0, mGlobals.OutputFileName, "could not open input file");
    237     goto FinishUp;
    238   }
    239   //
    240   // Read lines until we're done
    241   //
    242   LineCounter = 0;
    243   while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) {
    244     LineCounter++;
    245     if (IsCommentLine (Line)) {
    246       continue;
    247     }
    248     //
    249     // Convert to a GUID
    250     //
    251     if (StringToGuid (Line, &Guid) != EFI_SUCCESS) {
    252       Error (mGlobals.AprioriFileName, LineCounter, 0, "failed to convert GUID", NULL);
    253       goto FinishUp;
    254     }
    255     //
    256     // Write the guid to the output file
    257     //
    258     if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) {
    259       Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write GUID to output file");
    260       goto FinishUp;
    261     }
    262   }
    263   //
    264   // Write a null guid out to terminate the list
    265   //
    266   if (mGlobals.NullTerminate) {
    267     memset ((void *) &Guid, 0, sizeof (Guid));
    268     if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) {
    269       Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write NULL termination GUID to output file");
    270     }
    271   }
    272 
    273 FinishUp:
    274 
    275   if (AprioriFptr != NULL) {
    276     fclose (AprioriFptr);
    277   }
    278 
    279   if (BinFptr != NULL) {
    280     fclose (BinFptr);
    281   }
    282 
    283   return GetUtilityStatus ();
    284 }
    285 
    286 static
    287 BOOLEAN
    288 IsCommentLine (
    289   INT8    *Line
    290   )
    291 /*++
    292 
    293 Routine Description:
    294 
    295   GC_TODO: Add function description
    296 
    297 Arguments:
    298 
    299   Line  - GC_TODO: add argument description
    300 
    301 Returns:
    302 
    303   GC_TODO: add return values
    304 
    305 --*/
    306 {
    307   for (; isspace (*Line) && *Line; Line++)
    308     ;
    309 
    310   //
    311   // Allow # or // comments
    312   //
    313   if ((*Line == '#') || ((*Line == '/') && (*(Line + 1) == '/')) || (*Line == '\n') || (*Line == 0)) {
    314     return TRUE;
    315   }
    316 
    317   return FALSE;
    318 }
    319 //
    320 // Process the command-line arguments
    321 //
    322 static
    323 STATUS
    324 ProcessArgs (
    325   int   Argc,
    326   char  *Argv[]
    327   )
    328 /*++
    329 
    330 Routine Description:
    331 
    332   GC_TODO: Add function description
    333 
    334 Arguments:
    335 
    336   Argc  - GC_TODO: add argument description
    337   ]     - GC_TODO: add argument description
    338 
    339 Returns:
    340 
    341   GC_TODO: add return values
    342 
    343 --*/
    344 {
    345   //
    346   // Skip program name
    347   //
    348   Argc--;
    349   Argv++;
    350 
    351   //
    352   // Process until no more args
    353   //
    354   while (Argc) {
    355     //
    356     // -f AprioriFile
    357     //
    358     if (_stricmp (Argv[0], "-f") == 0) {
    359       //
    360       // check for one more arg
    361       //
    362       if (Argc > 1) {
    363         mGlobals.AprioriFileName = Argv[1];
    364       } else {
    365         Error (NULL, 0, 0, NULL, "missing filename with %s", Argv[0]);
    366         Usage ();
    367         return STATUS_ERROR;
    368       }
    369 
    370       Argc--;
    371       Argv++;
    372     } else if (_stricmp (Argv[0], "-i") == 0) {
    373       //
    374       // intelligent creation of output file. That is to say, if
    375       // there's already a file there, and it's the same as what
    376       // we'd create, then don't re-create. This is to support
    377       // incremental builds (that is to say, running nmake a second time
    378       // does nothing).
    379       //
    380       mGlobals.Intelligent = TRUE;
    381     } else if (_stricmp (Argv[0], "-v") == 0) {
    382       mGlobals.Verbose = TRUE;
    383     } else if (_stricmp (Argv[0], "-null") == 0) {
    384       mGlobals.NullTerminate = TRUE;
    385     } else if (_stricmp (Argv[0], "-o") == 0) {
    386       //
    387       // -o OutputFileName
    388       // check for one more arg
    389       //
    390       if (Argc > 1) {
    391         mGlobals.OutputFileName = Argv[1];
    392       } else {
    393         Error (NULL, 0, 0, NULL, "missing filename argument with %s", Argv[0]);
    394         Usage ();
    395         return STATUS_ERROR;
    396       }
    397 
    398       Argc--;
    399       Argv++;
    400     } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
    401       Usage ();
    402       return STATUS_ERROR;
    403     } else {
    404       Error (NULL, 0, 0, Argv[0], "unrecognized option");
    405       Usage ();
    406       return STATUS_ERROR;
    407     }
    408 
    409     Argc--;
    410     Argv++;
    411   }
    412   //
    413   // Had to specify the apriori input file and output file names
    414   //
    415   if (mGlobals.AprioriFileName == NULL) {
    416     Error (NULL, 0, 0, "must specify -f AprioriFile", NULL);
    417     Usage ();
    418     return STATUS_ERROR;
    419   }
    420 
    421   if (mGlobals.OutputFileName == NULL) {
    422     Error (NULL, 0, 0, "must specify -o OutputFile", NULL);
    423     Usage ();
    424     return STATUS_ERROR;
    425   }
    426 
    427   return STATUS_SUCCESS;
    428 }
    429 
    430 static
    431 void
    432 Usage (
    433   VOID
    434   )
    435 /*++
    436 
    437 Routine Description:
    438 
    439   Print usage information for this utility.
    440 
    441 Arguments:
    442 
    443   None.
    444 
    445 Returns:
    446 
    447   Nothing.
    448 
    449 --*/
    450 {
    451   int        Index;
    452   const char *Str[] = {
    453     UTILITY_NAME" "UTILITY_VERSION" - Intel Generate Apriori File Utility",
    454     "  Copyright (C), 2006 - 2008 Intel Corporation",
    455 
    456 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
    457     "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
    458 #endif
    459     "",
    460     "Usage:",
    461     "  "UTILITY_NAME" [OPTION]...",
    462     "Description:",
    463     "  Generate an Apriori file consumable by the DXE or PEI dispatcher.",
    464     "Options:",
    465     "  -h or -?         for this help information",
    466     "  -f AprioriFile   parse the GUID'ed files in AprioriFile (required)",
    467     "  -o OutputFile    write output to OutputFile (required)",
    468     "  -i               for intelligent re-creation of OutputFile",
    469     "  -null            to terminate the output file with a NULL GUID",
    470     "  -v               verbose option",
    471     NULL
    472   };
    473   for (Index = 0; Str[Index] != NULL; Index++) {
    474     fprintf (stdout, "%s\n", Str[Index]);
    475   }
    476 }
    477