Home | History | Annotate | Download | only in GuidChk
      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   GuidChk.c
     15 
     16 Abstract:
     17 
     18   Parse files in a directory and subdirectories to find all guid definitions.
     19   Then check them against each other to make sure there are no duplicates.
     20 
     21 --*/
     22 
     23 #include <stdio.h>
     24 #include <string.h>
     25 #include <stdlib.h>
     26 #include <ctype.h>
     27 
     28 #include "CommonUtils.h"
     29 #include "FileSearch.h"
     30 #include "UtilsMsgs.h"
     31 
     32 #define MAX_LINE_LEN  1024 // we concatenate lines sometimes
     33 // Define a structure that correlates filename extensions to an enumerated
     34 // type.
     35 //
     36 #ifdef MAX_PATH
     37 #undef MAX_PATH
     38 #define MAX_PATH  1024
     39 #endif
     40 
     41 #define UTILITY_NAME    "GuidChk"
     42 #define UTILITY_VERSION "v1.0"
     43 
     44 typedef struct {
     45   INT8  *Extension;
     46   INT8  ExtensionCode;
     47 } FILE_TYPE_TABLE_ENTRY;
     48 
     49 #define FILE_EXTENSION_UNKNOWN  0
     50 #define FILE_EXTENSION_C        1
     51 #define FILE_EXTENSION_H        2
     52 #define FILE_EXTENSION_IA32_ASM 3
     53 #define FILE_EXTENSION_IA32_INC 4
     54 #define FILE_EXTENSION_IA64_ASM 5
     55 #define FILE_EXTENSION_IA64_INC 6
     56 #define FILE_EXTENSION_PKG      7
     57 #define FILE_EXTENSION_INF      8
     58 
     59 FILE_TYPE_TABLE_ENTRY FileTypeTable[] = {
     60   ".c",
     61   FILE_EXTENSION_C,
     62   ".h",
     63   FILE_EXTENSION_H,
     64   ".inc",
     65   FILE_EXTENSION_IA32_INC,
     66   ".asm",
     67   FILE_EXTENSION_IA32_ASM,
     68   ".s",
     69   FILE_EXTENSION_IA64_ASM,
     70   ".pkg",
     71   FILE_EXTENSION_PKG,
     72   ".inf",
     73   FILE_EXTENSION_INF,
     74   ".i",
     75   FILE_EXTENSION_IA64_INC,
     76   NULL,
     77   0
     78 };
     79 
     80 typedef struct EFI_GUID {
     81   UINT32  Data1;
     82   UINT16  Data2;
     83   UINT16  Data3;
     84   UINT8   Data4[8];
     85 } EFI_GUID;
     86 
     87 typedef struct {
     88   INT8  Data[8];
     89   INT8  DataLen;
     90 } EFI_SIGNATURE;
     91 
     92 typedef struct _GUID_RECORD {
     93   struct _GUID_RECORD *Next;
     94   BOOLEAN             Reported;
     95   INT8                *FileName;
     96   INT8                *SymName;
     97   EFI_GUID            Guid;
     98 } GUID_RECORD;
     99 
    100 typedef struct _SIGNATURE_RECORD {
    101   struct _SIGNATURE_RECORD  *Next;
    102   BOOLEAN                   Reported;
    103   INT8                      *FileName;
    104   EFI_SIGNATURE             Signature;
    105 } SIGNATURE_RECORD;
    106 
    107 //
    108 // Utility options
    109 //
    110 typedef struct {
    111   INT8        DatabaseOutputFileName[MAX_PATH]; // with -b option
    112   STRING_LIST *ExcludeDirs;                     // list of directory names not to process
    113   STRING_LIST *ExcludeSubDirs;                  // list of directory names to not process subdirectories (build)
    114   STRING_LIST *ExcludeFiles;                    // list of files to exclude (make.inf)
    115   STRING_LIST *ExcludeExtensions;               // list of filename extensions to exclude (.inf, .pkg)
    116   BOOLEAN     Verbose;
    117   BOOLEAN     PrintFound;
    118   BOOLEAN     CheckGuids;
    119   BOOLEAN     CheckSignatures;
    120   BOOLEAN     GuidXReference;
    121 } OPTIONS;
    122 
    123 static
    124 STATUS
    125 ProcessArgs (
    126   int     Argc,
    127   char    *Argv[]
    128   );
    129 
    130 static
    131 VOID
    132 Usage (
    133   VOID
    134   );
    135 
    136 static
    137 STATUS
    138 ProcessDirectory (
    139   INT8        *Path,
    140   INT8        *DirectoryName
    141   );
    142 
    143 static
    144 STATUS
    145 ProcessFile (
    146   INT8                *DirectoryName,
    147   INT8                *FileName
    148   );
    149 
    150 static
    151 UINT32
    152 GetFileExtension (
    153   INT8        *FileName
    154   );
    155 
    156 static
    157 UINT32
    158 SkipWhiteSpace (
    159   INT8    *Str
    160   );
    161 
    162 static
    163 UINT32
    164 ValidSymbolName (
    165   INT8    *Name
    166   );
    167 
    168 static
    169 STATUS
    170 ProcessCFileGuids (
    171   INT8    *FileName
    172   );
    173 
    174 static
    175 STATUS
    176 AddSignature (
    177   INT8      *FileName,
    178   INT8      *StrDef,
    179   UINT32    SigSize
    180   );
    181 
    182 static
    183 STATUS
    184 ProcessCFileSigs (
    185   INT8    *FileName
    186   );
    187 
    188 static
    189 STATUS
    190 ProcessINFFileGuids (
    191   INT8    *FileName
    192   );
    193 
    194 static
    195 STATUS
    196 ProcessPkgFileGuids (
    197   INT8    *FileName
    198   );
    199 
    200 static
    201 STATUS
    202 ProcessIA32FileGuids (
    203   INT8    *FileName
    204   );
    205 
    206 static
    207 STATUS
    208 ProcessIA64FileGuids (
    209   INT8    *FileName
    210   );
    211 
    212 static
    213 BOOLEAN
    214 IsIA64GuidLine (
    215   INT8      *Line,
    216   UINT32    *GuidHigh,
    217   UINT32    *GuidLow,
    218   BOOLEAN   *Low,
    219   INT8      *SymName
    220   );
    221 
    222 static
    223 STATUS
    224 AddGuid11 (
    225   INT8      *FileName,
    226   UINT32    *Data,
    227   INT8      *SymName
    228   );
    229 
    230 static
    231 STATUS
    232 AddPkgGuid (
    233   INT8      *FileName,
    234   UINT32    *Data,
    235   UINT64    *Data64
    236   );
    237 
    238 static
    239 STATUS
    240 AddGuid16 (
    241   INT8      *FileName,
    242   UINT32    *Data
    243   );
    244 
    245 static
    246 STATUS
    247 AddGuid64x2 (
    248   INT8      *FileName,
    249   UINT32    DataHH,                             // Upper 32-bits of upper 64 bits of guid
    250   UINT32    DataHL,                             // Lower 32-bits of upper 64 bits
    251   UINT32    DataLH,
    252   UINT32    DataLL,
    253   INT8      *SymName
    254   );
    255 
    256 static
    257 VOID
    258 FreeGuids (
    259   VOID
    260   );
    261 
    262 static
    263 VOID
    264 FreeSigs (
    265   VOID
    266   );
    267 
    268 static
    269 STATUS
    270 CheckDuplicates (
    271   VOID
    272   );
    273 
    274 //
    275 // static
    276 // VOID
    277 // ReportGuid (
    278 //  INT8        *FileName,
    279 //  GUID_RECORD *FileRecord
    280 //  );
    281 //
    282 static
    283 VOID
    284 FreeOptions (
    285   VOID
    286   );
    287 
    288 static
    289 BOOLEAN
    290 CheckGuidData (
    291   UINT32    *GuidData,
    292   UINT32    DataCount
    293   );
    294 
    295 static
    296 VOID
    297 ConcatenateLines (
    298   FILE        *Fptr,
    299   INT8        *Line,
    300   UINT32      Len
    301   );
    302 
    303 /**************************** GLOBALS ****************************************/
    304 static GUID_RECORD      *gGuidList      = NULL;
    305 static SIGNATURE_RECORD *gSignatureList = NULL;
    306 static OPTIONS          gOptions;
    307 
    308 /*****************************************************************************/
    309 int
    310 main (
    311   int     Argc,
    312   char    *Argv[]
    313   )
    314 {
    315   INT8    *Cwd;
    316   STATUS  Status;
    317 
    318   SetUtilityName ("GuidChk");
    319   //
    320   // Get the current working directory and then process the command line
    321   // arguments.
    322   //
    323   Cwd     = _getcwd (NULL, 0);
    324   Status  = ProcessArgs (Argc, Argv);
    325   if (Status != STATUS_SUCCESS) {
    326     return Status;
    327   }
    328 
    329   if (gOptions.CheckGuids || gOptions.CheckSignatures) {
    330     Status = ProcessDirectory (Cwd, NULL);
    331     if (Status == STATUS_SUCCESS) {
    332       //
    333       // Check for duplicates
    334       //
    335       Status = CheckDuplicates ();
    336     }
    337   }
    338 
    339   if (gOptions.DatabaseOutputFileName[0] != 0) {
    340     CreateGuidList (gOptions.DatabaseOutputFileName);
    341   }
    342   //
    343   // Free up the memory
    344   //
    345   free (Cwd);
    346   FreeGuids ();
    347   FreeSigs ();
    348   FreeOptions ();
    349   return GetUtilityStatus ();
    350 }
    351 
    352 static
    353 STATUS
    354 ProcessArgs (
    355   int     Argc,
    356   char    *Argv[]
    357   )
    358 {
    359   STRING_LIST *StrList;
    360 
    361   memset ((char *) &gOptions, 0, sizeof (gOptions));
    362   //
    363   // skip over program name
    364   //
    365   Argc--;
    366   Argv++;
    367 
    368   if (Argc == 0) {
    369     Usage ();
    370     return STATUS_ERROR;
    371   }
    372 
    373   while (Argc > 0) {
    374     //
    375     // Look for options
    376     //
    377     if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
    378       switch (Argv[0][1]) {
    379       //
    380       // Help option
    381       //
    382       case 'h':
    383       case 'H':
    384       case '?':
    385         Usage ();
    386         return STATUS_ERROR;
    387         break;
    388 
    389       //
    390       // Check guids option
    391       //
    392       case 'g':
    393       case 'G':
    394         gOptions.CheckGuids = TRUE;
    395         break;
    396 
    397       //
    398       // Check signatures option
    399       //
    400       case 's':
    401       case 'S':
    402         gOptions.CheckSignatures = TRUE;
    403         break;
    404 
    405       //
    406       // Print guids found option
    407       //
    408       case 'p':
    409       case 'P':
    410         gOptions.PrintFound = TRUE;
    411         break;
    412 
    413       //
    414       // Exclude files option
    415       //
    416       case 'f':
    417       case 'F':
    418         //
    419         // Check for another arg
    420         //
    421         if (Argc < 2) {
    422           Error (NULL, 0, 0, Argv[0], "missing argument with option");
    423           Usage ();
    424           return STATUS_ERROR;
    425         }
    426 
    427         StrList = malloc (sizeof (STRING_LIST));
    428         if (StrList == NULL) {
    429           Error (NULL, 0, 0, "memory allocation failure", NULL);
    430           return STATUS_ERROR;
    431         }
    432 
    433         memset ((char *) StrList, 0, sizeof (STRING_LIST));
    434         StrList->Str          = Argv[1];
    435         StrList->Next         = gOptions.ExcludeFiles;
    436         gOptions.ExcludeFiles = StrList;
    437         Argc--;
    438         Argv++;
    439         break;
    440 
    441       //
    442       // Exclude directories option
    443       //
    444       case 'd':
    445       case 'D':
    446         //
    447         // Check for another arg
    448         //
    449         if (Argc < 2) {
    450           Error (NULL, 0, 0, Argv[0], "missing argument with option");
    451           Usage ();
    452           return STATUS_ERROR;
    453         }
    454 
    455         StrList = malloc (sizeof (STRING_LIST));
    456         if (StrList == NULL) {
    457           Error (NULL, 0, 0, "memory allocation failure", NULL);
    458           return STATUS_ERROR;
    459         }
    460 
    461         memset ((char *) StrList, 0, sizeof (STRING_LIST));
    462         StrList->Str          = Argv[1];
    463         StrList->Next         = gOptions.ExcludeDirs;
    464         gOptions.ExcludeDirs  = StrList;
    465         Argc--;
    466         Argv++;
    467         break;
    468 
    469       //
    470       // -u  exclude all subdirectories of a given directory option
    471       //
    472       case 'u':
    473       case 'U':
    474         //
    475         // Check for another arg
    476         //
    477         if (Argc < 2) {
    478           Error (NULL, 0, 0, Argv[0], "missing argument with option");
    479           Usage ();
    480           return STATUS_ERROR;
    481         }
    482 
    483         StrList = malloc (sizeof (STRING_LIST));
    484         if (StrList == NULL) {
    485           Error (NULL, 0, 0, "memory allocation failure", NULL);
    486           return STATUS_ERROR;
    487         }
    488 
    489         memset ((char *) StrList, 0, sizeof (STRING_LIST));
    490         StrList->Str            = Argv[1];
    491         StrList->Next           = gOptions.ExcludeSubDirs;
    492         gOptions.ExcludeSubDirs = StrList;
    493         Argc--;
    494         Argv++;
    495         break;
    496 
    497       //
    498       // -e  exclude by filename extension option
    499       //
    500       case 'e':
    501       case 'E':
    502         //
    503         // Check for another arg
    504         //
    505         if (Argc < 2) {
    506           Error (NULL, 0, 0, Argv[0], "missing argument with option");
    507           Usage ();
    508           return STATUS_ERROR;
    509         }
    510 
    511         StrList = malloc (sizeof (STRING_LIST));
    512         if (StrList == NULL) {
    513           Error (NULL, 0, 0, "memory allocation failure", NULL);
    514           return STATUS_ERROR;
    515         }
    516 
    517         memset ((char *) StrList, 0, sizeof (STRING_LIST));
    518         //
    519         // Let them put a * in front of the filename extension
    520         //
    521         StrList->Str = Argv[1];
    522         if (StrList->Str[0] == '*') {
    523           StrList->Str++;
    524         }
    525 
    526         StrList->Next               = gOptions.ExcludeExtensions;
    527         gOptions.ExcludeExtensions  = StrList;
    528         Argc--;
    529         Argv++;
    530         break;
    531 
    532       //
    533       // Print guid with matching symbol name for guid definitions found
    534       //
    535       case 'x':
    536       case 'X':
    537         gOptions.GuidXReference = TRUE;
    538         break;
    539 
    540       //
    541       // -b   Print the internal database list to a file
    542       //
    543       case 'b':
    544       case 'B':
    545         //
    546         // Check for one more arg
    547         //
    548         if (Argc < 2) {
    549           Error (NULL, 0, 0, Argv[0], "must specify file name with option");
    550           Usage ();
    551           return STATUS_ERROR;
    552         }
    553 
    554         strcpy (gOptions.DatabaseOutputFileName, Argv[1]);
    555         Argc--;
    556         Argv++;
    557         break;
    558 
    559       default:
    560         Error (NULL, 0, 0, Argv[0], "invalid option");
    561         Usage ();
    562         return STATUS_ERROR;
    563       }
    564     } else {
    565       break;
    566     }
    567     //
    568     // Next arg
    569     //
    570     Argc--;
    571     Argv++;
    572   }
    573 
    574   if (Argc > 0) {
    575     Error (NULL, 0, 0, Argv[0], "invalid argument");
    576     Usage ();
    577     return STATUS_ERROR;
    578   }
    579   //
    580   // Have to check signatures, GUIDs, or dump the GUID database.
    581   //
    582   if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) {
    583     Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b");
    584     Usage ();
    585     return STATUS_ERROR;
    586   }
    587 
    588   return STATUS_SUCCESS;
    589 }
    590 //
    591 // Print usage instructions
    592 //
    593 static
    594 VOID
    595 Usage (
    596   VOID
    597   )
    598 {
    599   int         Index;
    600   const char  *Str[] = {
    601     UTILITY_NAME" "UTILITY_VERSION" - Intel GUID Check Utility",
    602     "  Copyright (C), 2004 - 2008 Intel Corporation",
    603 
    604 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
    605     "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
    606 #endif
    607     "",
    608     "Usage:",
    609     "  "UTILITY_NAME" [OPTION]...",
    610     "Description:",
    611     "  Scan files for duplicate GUID or signature definitions.",
    612     "Options:",
    613     "  -d dirname     exclude searching of a directory",
    614     "  -f filename    exclude searching of a file",
    615     "  -e extension   exclude searching of files by extension",
    616     "  -p             print all GUIDS found",
    617     "  -g             check for duplicate guids",
    618     "  -s             check for duplicate signatures",
    619     "  -x             print guid+defined symbol name",
    620     "  -b outfile     write internal GUID+basename list to outfile",
    621     "  -u dirname     exclude searching all subdirectories of a directory",
    622     "  -h -?          print this help text",
    623     "Example Usage:",
    624     "  GuidChk -g -u build -d fv -f make.inf -e .pkg",
    625     NULL
    626   };
    627   for (Index = 0; Str[Index] != NULL; Index++) {
    628     fprintf (stdout, "%s\n", Str[Index]);
    629   }
    630 }
    631 //
    632 // Process an entire directory by name
    633 //
    634 static
    635 STATUS
    636 ProcessDirectory (
    637   INT8          *Path,
    638   INT8          *DirectoryName
    639   )
    640 {
    641   FILE_SEARCH_DATA  FSData;
    642   char              *FileMask;
    643   BOOLEAN           Done;
    644   UINT32            Len;
    645   BOOLEAN           NoSubdirs;
    646   STRING_LIST       *SLPtr;
    647 
    648   //
    649   // Root directory may be null
    650   //
    651   if (DirectoryName != NULL) {
    652     //
    653     // printf ("Processing directory: %s\n", DirectoryName);
    654     //
    655   }
    656   //
    657   // Initialize our file searching
    658   //
    659   FileSearchInit (&FSData);
    660 
    661   //
    662   // Exclude some directories, files, and extensions
    663   //
    664   FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs);
    665   FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions);
    666   FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles);
    667   //
    668   // See if this directory is in the list of directories that they
    669   // don't want to process subdirectories of
    670   //
    671   NoSubdirs = FALSE;
    672   if (DirectoryName != NULL) {
    673     for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) {
    674       if (_stricmp (SLPtr->Str, DirectoryName) == 0) {
    675         //
    676         // printf ("not processing subdirectories of %s\n", DirectoryName);
    677         //
    678         NoSubdirs = TRUE;
    679         break;
    680       }
    681     }
    682   }
    683   //
    684   // Create a filemask of files to search for. We'll append "\*.*" on the
    685   // end, so allocate some extra bytes.
    686   //
    687   Len = strlen (Path) + 10;
    688   if (DirectoryName != NULL) {
    689     Len += strlen (DirectoryName);
    690   }
    691 
    692   FileMask = malloc (Len);
    693   if (FileMask == NULL) {
    694     Error (NULL, 0, 0, "memory allocation failure", NULL);
    695     return STATUS_ERROR;
    696   }
    697   //
    698   // Now put it all together
    699   //
    700   strcpy (FileMask, Path);
    701   if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) {
    702     strcat (FileMask, "\\");
    703     strcat (FileMask, DirectoryName);
    704   }
    705 
    706   strcat (FileMask, "\\*.*");
    707 
    708   //
    709   // Start file searching for files and directories
    710   //
    711   if (FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR) == STATUS_SUCCESS) {
    712     Done = FALSE;
    713   } else {
    714     Done = TRUE;
    715   }
    716 
    717   //
    718   // Now hack the "\*.*" off the end of the filemask so we can use it to pass
    719   // the full directory path on recursive calls to process directories.
    720   //
    721   FileMask[strlen (FileMask) - 4] = 0;
    722 
    723   //
    724   // Loop until no more files
    725   //
    726   while (!Done) {
    727     //
    728     // printf ("Found %s...", FSData.FileName);
    729     //
    730     if (FSData.FileFlags & FILE_SEARCH_DIR) {
    731       //
    732       // printf ("directory\n");
    733       //
    734       if (!NoSubdirs) {
    735         ProcessDirectory (FileMask, FSData.FileName);
    736       }
    737     } else if (FSData.FileFlags & FILE_SEARCH_FILE) {
    738       //
    739       // printf ("file\n");
    740       //
    741       ProcessFile (FileMask, FSData.FileName);
    742     } else {
    743       //
    744       // printf ("unknown\n");
    745       //
    746     }
    747 
    748     if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) {
    749       Done = TRUE;
    750     }
    751   }
    752   //
    753   // Free up allocated memory
    754   //
    755   free (FileMask);
    756 
    757   //
    758   // Free up our file searching
    759   //
    760   FileSearchDestroy (&FSData);
    761 
    762   return STATUS_SUCCESS;
    763 }
    764 //
    765 // Process a single file.
    766 //
    767 static
    768 STATUS
    769 ProcessFile (
    770   INT8                *DirectoryName,
    771   INT8                *FileName
    772   )
    773 {
    774   STATUS  Status;
    775   UINT32  FileExtension;
    776   INT8    FullFileName[MAX_PATH];
    777 
    778   Status = STATUS_SUCCESS;
    779 
    780   sprintf (FullFileName, "%s\\%s", DirectoryName, FileName);
    781   //
    782   // printf ("Found file: %s\n", FullFileName);
    783   //
    784   FileExtension = GetFileExtension (FileName);
    785 
    786   //
    787   // Process these for GUID checks
    788   //
    789   if (gOptions.CheckGuids) {
    790     switch (FileExtension) {
    791     case FILE_EXTENSION_C:
    792     case FILE_EXTENSION_H:
    793       Status = ProcessCFileGuids (FullFileName);
    794       break;
    795 
    796     case FILE_EXTENSION_PKG:
    797       Status = ProcessPkgFileGuids (FullFileName);
    798       break;
    799 
    800     case FILE_EXTENSION_IA32_INC:
    801     case FILE_EXTENSION_IA32_ASM:
    802       Status = ProcessIA32FileGuids (FullFileName);
    803       break;
    804 
    805     case FILE_EXTENSION_INF:
    806       Status = ProcessINFFileGuids (FullFileName);
    807       break;
    808 
    809     case FILE_EXTENSION_IA64_INC:
    810     case FILE_EXTENSION_IA64_ASM:
    811       Status = ProcessIA64FileGuids (FullFileName);
    812       break;
    813 
    814     default:
    815       //
    816       // No errors anyway
    817       //
    818       Status = STATUS_SUCCESS;
    819       break;
    820     }
    821   }
    822 
    823   if (gOptions.CheckSignatures) {
    824     switch (FileExtension) {
    825     case FILE_EXTENSION_C:
    826     case FILE_EXTENSION_H:
    827       Status = ProcessCFileSigs (FullFileName);
    828       break;
    829 
    830     default:
    831       //
    832       // No errors anyway
    833       //
    834       Status = STATUS_SUCCESS;
    835       break;
    836     }
    837   }
    838 
    839   return Status;
    840 }
    841 //
    842 // Return a code indicating the file name extension.
    843 //
    844 static
    845 UINT32
    846 GetFileExtension (
    847   INT8        *FileName
    848   )
    849 {
    850   INT8  *Extension;
    851   int   Index;
    852 
    853   //
    854   // Look back for a filename extension
    855   //
    856   for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) {
    857     if (*Extension == '.') {
    858       for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) {
    859         if (_stricmp (FileTypeTable[Index].Extension, Extension) == 0) {
    860           return FileTypeTable[Index].ExtensionCode;
    861         }
    862       }
    863     }
    864   }
    865 
    866   return FILE_TYPE_UNKNOWN;
    867 }
    868 //
    869 // Process a .pkg file.
    870 //
    871 // Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
    872 //
    873 static
    874 STATUS
    875 ProcessPkgFileGuids (
    876   INT8    *FileName
    877   )
    878 {
    879   FILE    *Fptr;
    880   INT8    Line[MAX_LINE_LEN * 2];
    881   INT8    *Cptr;
    882   INT8    *Cptr2;
    883   UINT32  GuidScan[11];
    884   UINT64  Guid64;
    885 
    886   if ((Fptr = fopen (FileName, "r")) == NULL) {
    887     Error (NULL, 0, 0, FileName, "could not open input file for reading");
    888     return STATUS_ERROR;
    889   }
    890   //
    891   // Read lines from the file until done
    892   //
    893   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
    894     Cptr = Line;
    895     Cptr += SkipWhiteSpace (Line);
    896     if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) {
    897       Cptr += 12;
    898       Cptr += SkipWhiteSpace (Cptr);
    899       if (*Cptr == '=') {
    900         Cptr++;
    901         Cptr += SkipWhiteSpace (Cptr + 1);
    902         //
    903         // Blank out dashes on the line.
    904         //
    905         for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
    906           if (*Cptr2 == '-') {
    907             *Cptr2 = ' ';
    908           }
    909         }
    910 
    911         if (sscanf (
    912               Cptr,
    913               "%X %X %X %X %I64X",
    914               &GuidScan[0],
    915               &GuidScan[1],
    916               &GuidScan[2],
    917               &GuidScan[3],
    918               &Guid64
    919               ) == 5) {
    920           AddPkgGuid (FileName, GuidScan, &Guid64);
    921         } else {
    922           DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
    923         }
    924       }
    925     }
    926   }
    927 
    928   fclose (Fptr);
    929   return STATUS_SUCCESS;
    930 }
    931 //
    932 // Process an IA32 assembly file.
    933 //
    934 // Look for:
    935 // FIND_FD_GUID_VAL equ  01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h
    936 // PEI_GUID_FileNameGuid_Gmch815  equ  081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h
    937 //
    938 static
    939 STATUS
    940 ProcessIA32FileGuids (
    941   INT8    *FileName
    942   )
    943 {
    944   FILE    *Fptr;
    945   INT8    Line[MAX_LINE_LEN];
    946   INT8    *Cptr;
    947   INT8    CSave;
    948   INT8    *CSavePtr;
    949   UINT32  Len;
    950   UINT32  GuidData[16];
    951   UINT32  Index;
    952 
    953   if ((Fptr = fopen (FileName, "r")) == NULL) {
    954     Error (NULL, 0, 0, FileName, "could not open input file for reading");
    955     return STATUS_ERROR;
    956   }
    957   //
    958   // Read lines from the file until done
    959   //
    960   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
    961     Cptr = Line;
    962     Cptr += SkipWhiteSpace (Line);
    963     //
    964     // Look for xxxGUIDyyy equ 01h, 02h, 03h, ...
    965     //
    966     Len = ValidSymbolName (Cptr);
    967     if (Len) {
    968       //
    969       // Terminate the line after the symbol name, then look for "guid" in
    970       // the name.
    971       //
    972       CSavePtr  = Cptr + Len;
    973       CSave     = *CSavePtr;
    974       *CSavePtr = 0;
    975       while (*Cptr) {
    976         if (_strnicmp (Cptr, "guid", 4) == 0) {
    977           break;
    978         }
    979 
    980         Cptr++;
    981       }
    982       //
    983       // If we found the string "guid", continue
    984       //
    985       if (*Cptr) {
    986         //
    987         // Restore the character on the line where we null-terminated the symbol
    988         //
    989         *CSavePtr = CSave;
    990         Cptr      = CSavePtr;
    991         Len       = SkipWhiteSpace (Cptr);
    992         //
    993         // Had to be some white space
    994         //
    995         if (Len) {
    996           Cptr += Len;
    997           //
    998           // now look for "equ"
    999           //
   1000           if (_strnicmp (Cptr, "equ", 3) == 0) {
   1001             Cptr += 3;
   1002             Cptr += SkipWhiteSpace (Cptr);
   1003             //
   1004             // Now scan all the data
   1005             //
   1006             for (Index = 0; Index < 16; Index++) {
   1007               if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) {
   1008                 break;
   1009               }
   1010               //
   1011               // Skip to next
   1012               //
   1013               while (isxdigit (*Cptr)) {
   1014                 Cptr++;
   1015               }
   1016 
   1017               if ((*Cptr != 'h') && (*Cptr != 'H')) {
   1018                 break;
   1019               } else {
   1020                 Cptr++;
   1021                 while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) {
   1022                   Cptr++;
   1023                 }
   1024               }
   1025             }
   1026             //
   1027             // Now see which form we had
   1028             //
   1029             if (Index == 16) {
   1030               AddGuid16 (FileName, GuidData);
   1031             } else if (Index == 11) {
   1032               AddGuid11 (FileName, GuidData, NULL);
   1033             }
   1034           }
   1035         }
   1036       }
   1037     }
   1038   }
   1039 
   1040   fclose (Fptr);
   1041   return STATUS_SUCCESS;
   1042 }
   1043 //
   1044 // Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list
   1045 // of guids.
   1046 //
   1047 static
   1048 STATUS
   1049 AddGuid16 (
   1050   INT8      *FileName,
   1051   UINT32    *Data
   1052   )
   1053 {
   1054   GUID_RECORD *NewRec;
   1055   int         Index;
   1056 
   1057   //
   1058   // Sanity check the data
   1059   //
   1060   if (!CheckGuidData (Data, 16)) {
   1061     return STATUS_ERROR;
   1062   }
   1063   //
   1064   // Allocate memory for a new guid structure
   1065   //
   1066   NewRec = malloc (sizeof (GUID_RECORD));
   1067   if (NewRec == NULL) {
   1068     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1069     return STATUS_ERROR;
   1070   }
   1071 
   1072   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
   1073   NewRec->FileName = malloc (strlen (FileName) + 1);
   1074   if (NewRec->FileName == NULL) {
   1075     free (NewRec);
   1076     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1077     return STATUS_ERROR;
   1078   }
   1079 
   1080   strcpy (NewRec->FileName, FileName);
   1081   NewRec->Guid.Data1  = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24));
   1082   NewRec->Guid.Data2  = (UINT16) (Data[4] | (Data[5] << 8));
   1083   NewRec->Guid.Data3  = (UINT16) (Data[6] | (Data[7] << 8));
   1084   for (Index = 0; Index < 8; Index++) {
   1085     NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8];
   1086   }
   1087   //
   1088   // Add it to the list
   1089   //
   1090   NewRec->Next  = gGuidList;
   1091   gGuidList     = NewRec;
   1092 
   1093   //
   1094   // Report it
   1095   // ReportGuid (FileName, NewRec);
   1096   //
   1097   return STATUS_SUCCESS;
   1098 }
   1099 //
   1100 // Add a GUID defined as GuidLow: 0x1122334455667788
   1101 //                       GuidHi:  0x99AABBCCDDEEFF00
   1102 //
   1103 // These are equivalent:
   1104 // { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }
   1105 //    and:
   1106 // Low: 00FFEEDDCCBBAA99
   1107 // Hi:  7788556611223344
   1108 //
   1109 static
   1110 STATUS
   1111 AddGuid64x2 (
   1112   INT8      *FileName,
   1113   UINT32    DataHH, // Upper 32-bits of upper 64 bits of guid
   1114   UINT32    DataHL, // Lower 32-bits of upper 64 bits
   1115   UINT32    DataLH,
   1116   UINT32    DataLL,
   1117   INT8      *SymName
   1118   )
   1119 {
   1120   GUID_RECORD *NewRec;
   1121   int         Index;
   1122 
   1123   //
   1124   // Allocate memory for a new guid structure
   1125   //
   1126   NewRec = malloc (sizeof (GUID_RECORD));
   1127   if (NewRec == NULL) {
   1128     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1129     return STATUS_ERROR;
   1130   }
   1131 
   1132   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
   1133   NewRec->FileName = malloc (strlen (FileName) + 1);
   1134   if (NewRec->FileName == NULL) {
   1135     free (NewRec);
   1136     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1137     return STATUS_ERROR;
   1138   }
   1139 
   1140   strcpy (NewRec->FileName, FileName);
   1141   NewRec->Guid.Data1  = DataHL;
   1142   NewRec->Guid.Data2  = (UINT16) DataHH;
   1143   NewRec->Guid.Data3  = (UINT16) (DataHH >> 16);
   1144   for (Index = 0; Index < 4; Index++) {
   1145     NewRec->Guid.Data4[Index] = (UINT8) DataLL;
   1146     DataLL >>= 8;
   1147   }
   1148 
   1149   for (Index = 0; Index < 4; Index++) {
   1150     NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH;
   1151     DataLH >>= 8;
   1152   }
   1153 
   1154   if (SymName != NULL) {
   1155     NewRec->SymName = malloc (strlen (SymName) + 1);
   1156     if (NewRec->SymName == NULL) {
   1157       free (NewRec);
   1158       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1159       return STATUS_ERROR;
   1160     }
   1161     strcpy (NewRec->SymName, SymName);
   1162   }
   1163 
   1164   //
   1165   // Add it to the list
   1166   //
   1167   NewRec->Next  = gGuidList;
   1168   gGuidList     = NewRec;
   1169 
   1170   //
   1171   // Report it
   1172   // ReportGuid (FileName, NewRec);
   1173   //
   1174   return STATUS_SUCCESS;
   1175 }
   1176 //
   1177 // Process INF files. Look for:
   1178 // FILE_GUID            = 240612B6-A063-11d4-9A3A-0090273FC14D
   1179 //
   1180 static
   1181 STATUS
   1182 ProcessINFFileGuids (
   1183   INT8    *FileName
   1184   )
   1185 {
   1186   FILE    *Fptr;
   1187   INT8    Line[MAX_LINE_LEN * 2];
   1188   INT8    *Cptr;
   1189   INT8    *Cptr2;
   1190   UINT32  GuidScan[11];
   1191   UINT64  Guid64;
   1192 
   1193   if ((Fptr = fopen (FileName, "r")) == NULL) {
   1194     Error (NULL, 0, 0, FileName, "could not open input file for reading");
   1195     return STATUS_ERROR;
   1196   }
   1197   //
   1198   // Read lines from the file until done
   1199   //
   1200   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
   1201     Cptr = Line;
   1202     Cptr += SkipWhiteSpace (Line);
   1203     if (strncmp (Cptr, "FILE_GUID", 9) == 0) {
   1204       Cptr += 9;
   1205       Cptr += SkipWhiteSpace (Cptr);
   1206       if (*Cptr == '=') {
   1207         Cptr++;
   1208         Cptr += SkipWhiteSpace (Cptr + 1);
   1209         //
   1210         // Blank out dashes on the line.
   1211         //
   1212         for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
   1213           if (*Cptr2 == '-') {
   1214             *Cptr2 = ' ';
   1215           }
   1216         }
   1217 
   1218         if (sscanf (
   1219               Cptr,
   1220               "%X %X %X %X %I64X",
   1221               &GuidScan[0],
   1222               &GuidScan[1],
   1223               &GuidScan[2],
   1224               &GuidScan[3],
   1225               &Guid64
   1226               ) == 5) {
   1227           AddPkgGuid (FileName, GuidScan, &Guid64);
   1228         } else {
   1229           DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
   1230         }
   1231       }
   1232     }
   1233   }
   1234 
   1235   fclose (Fptr);
   1236   return STATUS_SUCCESS;
   1237 }
   1238 //
   1239 // Parse ('g','m','a','p','a','b','c','d')
   1240 //
   1241 static
   1242 STATUS
   1243 AddSignature (
   1244   INT8      *FileName,
   1245   INT8      *StrDef,
   1246   UINT32    SigSize
   1247   )
   1248 {
   1249   SIGNATURE_RECORD  *NewRec;
   1250   INT8              *Cptr;
   1251   UINT32            Index;
   1252   BOOLEAN           Fail;
   1253 
   1254   //
   1255   // Allocate memory for the new record
   1256   //
   1257   Fail    = FALSE;
   1258   NewRec  = malloc (sizeof (SIGNATURE_RECORD));
   1259 
   1260   if (NewRec == NULL) {
   1261     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1262     return STATUS_ERROR;
   1263   }
   1264   memset ((char *) NewRec, 0, sizeof (SIGNATURE_RECORD));
   1265 
   1266   //
   1267   // Allocate memory to save the file name
   1268   //
   1269   NewRec->FileName = malloc (strlen (FileName) + 1);
   1270   if (NewRec->FileName == NULL) {
   1271     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1272     free (NewRec);
   1273     return STATUS_ERROR;
   1274   }
   1275   //
   1276   // Fill in the fields
   1277   //
   1278   strcpy (NewRec->FileName, FileName);
   1279   NewRec->Signature.DataLen = (UINT8) SigSize;
   1280   //
   1281   // Skip to open parenthesis
   1282   //
   1283   Cptr = StrDef;
   1284   Cptr += SkipWhiteSpace (Cptr);
   1285   if (*Cptr != '(') {
   1286     Fail = TRUE;
   1287     goto Done;
   1288   }
   1289 
   1290   Cptr++;
   1291   //
   1292   // Skip to first ' and start processing
   1293   //
   1294   while (*Cptr && (*Cptr != '\'')) {
   1295     Cptr++;
   1296   }
   1297 
   1298   for (Index = 0; Index < SigSize; Index++) {
   1299     if (*Cptr == '\'') {
   1300       Cptr++;
   1301       NewRec->Signature.Data[Index] = (INT8) *Cptr;
   1302       //
   1303       // Skip to closing quote
   1304       //
   1305       Cptr++;
   1306       if (*Cptr != '\'') {
   1307         Fail = TRUE;
   1308         break;
   1309       }
   1310       //
   1311       // Skip over closing quote, go to next one
   1312       //
   1313       Cptr++;
   1314       while (*Cptr && (*Cptr != '\'')) {
   1315         Cptr++;
   1316       }
   1317     } else {
   1318       Fail = TRUE;
   1319       DebugMsg (NULL, 0, 0, FileName, "failed to parse signature");
   1320       break;
   1321     }
   1322   }
   1323 
   1324 Done:
   1325   if (Fail) {
   1326     free (NewRec->FileName);
   1327     free (NewRec);
   1328     return STATUS_ERROR;
   1329   }
   1330 
   1331   NewRec->Next    = gSignatureList;
   1332   gSignatureList  = NewRec;
   1333   return STATUS_SUCCESS;
   1334 }
   1335 //
   1336 // Look for:
   1337 // #define POOL_HEAD_SIGNATURE         EFI_SIGNATURE_16('p','h')
   1338 // #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_32('g','m','a','p')
   1339 // #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_64('g','m','a','p','a','b','c','d')
   1340 //
   1341 static
   1342 STATUS
   1343 ProcessCFileSigs (
   1344   INT8    *FileName
   1345   )
   1346 {
   1347   FILE    *Fptr;
   1348   INT8    Line[MAX_LINE_LEN * 2];
   1349   INT8    *Cptr;
   1350   UINT32  Len;
   1351 
   1352   if ((Fptr = fopen (FileName, "r")) == NULL) {
   1353     Error (NULL, 0, 0, FileName, "could not open input file for reading");
   1354     return STATUS_ERROR;
   1355   }
   1356   //
   1357   // Read lines from the file until done
   1358   //
   1359   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
   1360     Cptr = Line;
   1361     Cptr += SkipWhiteSpace (Line);
   1362     //
   1363     // look for #define EFI_SIGNATURE_xx value
   1364     //
   1365     if (*Cptr == '#') {
   1366       Cptr++;
   1367       Cptr += SkipWhiteSpace (Cptr);
   1368       //
   1369       // Look for "define"
   1370       //
   1371       if (!strncmp (Cptr, "define", 6)) {
   1372         Cptr += 6;
   1373         //
   1374         // Better be whitespace
   1375         //
   1376         Len = SkipWhiteSpace (Cptr);
   1377         if (Len) {
   1378           Cptr += Len;
   1379           //
   1380           // See if it's a valid symbol name
   1381           //
   1382           Len = ValidSymbolName (Cptr);
   1383           if (Len) {
   1384             //
   1385             // It is a valid symbol name. See if there's line continuation,
   1386             // and if so, read more lines.
   1387             // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"
   1388             //
   1389             ConcatenateLines (Fptr, Line, sizeof(Line));
   1390 
   1391             Cptr += Len;
   1392             Cptr += SkipWhiteSpace (Cptr);
   1393             if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) {
   1394               AddSignature (FileName, Cptr + 16, 2);
   1395             } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) {
   1396               AddSignature (FileName, Cptr + 16, 4);
   1397             } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) {
   1398               AddSignature (FileName, Cptr + 16, 8);
   1399             }
   1400           }
   1401         }
   1402       }
   1403     }
   1404   }
   1405 
   1406   fclose (Fptr);
   1407   return STATUS_SUCCESS;
   1408 }
   1409 //
   1410 // look for #define xxxGUIDyyy { 0x...}
   1411 // xxx EFI_GUID  GuidName = { 0x... };
   1412 //
   1413 static
   1414 STATUS
   1415 ProcessCFileGuids (
   1416   INT8    *FileName
   1417   )
   1418 {
   1419   FILE    *Fptr;
   1420   INT8    Line[MAX_LINE_LEN * 2];
   1421   INT8    *Cptr;
   1422   INT8    *CSavePtr;
   1423   INT8    *TempCptr;
   1424   INT8    *SymName;
   1425   UINT32  Len;
   1426   UINT32  LineLen;
   1427   UINT32  GuidScan[11];
   1428 
   1429   if ((Fptr = fopen (FileName, "r")) == NULL) {
   1430     Error (NULL, 0, 0, FileName, "could not open input file for reading");
   1431     return STATUS_ERROR;
   1432   }
   1433   //
   1434   // Read lines from the file until done
   1435   //
   1436   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
   1437     Cptr = Line;
   1438     Cptr += SkipWhiteSpace (Line);
   1439     //
   1440     // look for #define xxxGUIDxxx value
   1441     //
   1442     if (*Cptr == '#') {
   1443       Cptr++;
   1444       Cptr += SkipWhiteSpace (Cptr);
   1445       //
   1446       // Look for "define"
   1447       //
   1448       if (!strncmp (Cptr, "define", 6)) {
   1449 DefineLine:
   1450         Cptr += 6;
   1451         //
   1452         // Better be whitespace
   1453         //
   1454         Len = SkipWhiteSpace (Cptr);
   1455         if (Len) {
   1456           Cptr += Len;
   1457           //
   1458           // See if it's a valid symbol name
   1459           //
   1460           Len = ValidSymbolName (Cptr);
   1461           if (Len) {
   1462             //
   1463             // It is a valid symbol name. See if there's line continuation,
   1464             // and if so, read more lines.
   1465             // Then truncate after the symbol name, look for the string "GUID",
   1466             // and continue.
   1467             //
   1468             SymName = Cptr;
   1469             ConcatenateLines (Fptr, Line, sizeof(Line));
   1470 
   1471             //
   1472             // Now look for { 0x....... }
   1473             //
   1474             CSavePtr  = Cptr + Len;
   1475             Cptr += Len;
   1476             Cptr += SkipWhiteSpace (Cptr);
   1477             if (*Cptr == '{') {
   1478               Cptr++;
   1479               //
   1480               // Blank out 'L', 'l', '{', '}', ',' on the line.
   1481               //
   1482               for (TempCptr = Cptr; *TempCptr; TempCptr++) {
   1483                 if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
   1484                     (*TempCptr == '}') || (*TempCptr == ',')) {
   1485                   *TempCptr       = ' ';
   1486                 }
   1487               }
   1488 
   1489               if (sscanf (
   1490                     Cptr,
   1491                     "%X %X %X %X %X %X %X %X %X %X %X",
   1492                     &GuidScan[0],
   1493                     &GuidScan[1],
   1494                     &GuidScan[2],
   1495                     &GuidScan[3],
   1496                     &GuidScan[4],
   1497                     &GuidScan[5],
   1498                     &GuidScan[6],
   1499                     &GuidScan[7],
   1500                     &GuidScan[8],
   1501                     &GuidScan[9],
   1502                     &GuidScan[10]
   1503                     ) == 11) {
   1504                 *CSavePtr = '\0';
   1505                 AddGuid11 (FileName, GuidScan, SymName);
   1506               }
   1507             }
   1508           }
   1509         }
   1510       }
   1511     //
   1512     // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };
   1513     //
   1514     } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {
   1515       //
   1516       // Read more lines until met ';'
   1517       //
   1518       ConcatenateLines (Fptr, Line, sizeof(Line));
   1519       while (strstr (Line, ";") == NULL) {
   1520         LineLen = strlen (Line);
   1521         Len = sizeof(Line) - LineLen;
   1522         if (Len <= 1) {
   1523           break;
   1524         }
   1525         if (Line[LineLen - 1] == '\n') {
   1526           Cptr = Line + LineLen - 1;
   1527           *Cptr = '\0';
   1528           if (fgets (Cptr, Len, Fptr) == NULL){
   1529             break;
   1530           }
   1531           ConcatenateLines (Fptr, Line, sizeof(Line));
   1532         } else {
   1533           Cptr = Line + LineLen;
   1534           *Cptr = '\0';
   1535           if (fgets (Cptr, Len, Fptr) == NULL) {
   1536             break;
   1537           }
   1538           ConcatenateLines (Fptr, Line, sizeof(Line));
   1539         }
   1540 
   1541         //
   1542         // EFI_GUID may appear in comments wihout end of ';' which may cause
   1543         // ignoring of new #define, so handle it here.
   1544         //
   1545         Cptr += SkipWhiteSpace (Cptr);
   1546         if (*Cptr == '#') {
   1547           Cptr++;
   1548           Cptr += SkipWhiteSpace (Cptr);
   1549           if (!strncmp (Cptr, "define", 6)) {
   1550             goto DefineLine;
   1551           }
   1552         }
   1553       }
   1554 
   1555       Cptr = CSavePtr + 8;
   1556       Cptr += SkipWhiteSpace (Cptr);
   1557       //
   1558       // Should be variable name next
   1559       //
   1560       Len     = ValidSymbolName (Cptr);
   1561       SymName = Cptr;
   1562       Cptr += Len;
   1563       CSavePtr = Cptr;
   1564       Cptr += SkipWhiteSpace (Cptr);
   1565       if (*Cptr == '=') {
   1566         *CSavePtr = '\0';
   1567         Cptr++;
   1568         Cptr += SkipWhiteSpace (Cptr);
   1569         //
   1570         // Should be open-brace next to define guid
   1571         //
   1572         if (*Cptr == '{') {
   1573           Cptr++;
   1574           //
   1575           // Blank out 'L', 'l', '{', '}', ',' on the line.
   1576           //
   1577           for (TempCptr = Cptr; *TempCptr; TempCptr++) {
   1578             if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
   1579                 (*TempCptr == '}') || (*TempCptr == ',')) {
   1580               *TempCptr       = ' ';
   1581             }
   1582           }
   1583 
   1584           if (sscanf (
   1585                 Cptr,
   1586                 "%X %X %X %X %X %X %X %X %X %X %X",
   1587                 &GuidScan[0],
   1588                 &GuidScan[1],
   1589                 &GuidScan[2],
   1590                 &GuidScan[3],
   1591                 &GuidScan[4],
   1592                 &GuidScan[5],
   1593                 &GuidScan[6],
   1594                 &GuidScan[7],
   1595                 &GuidScan[8],
   1596                 &GuidScan[9],
   1597                 &GuidScan[10]
   1598                 ) == 11) {
   1599             AddGuid11 (FileName, GuidScan, SymName);
   1600           }
   1601         }
   1602       }
   1603     }
   1604   }
   1605 
   1606   fclose (Fptr);
   1607   return STATUS_SUCCESS;
   1608 }
   1609 //
   1610 // Process Intel Itanium(TM) GUID definitions. Look for:
   1611 // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
   1612 // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
   1613 // in either order.
   1614 // This function assumes no blank lines between definitions.
   1615 //
   1616 static
   1617 STATUS
   1618 ProcessIA64FileGuids (
   1619   INT8    *FileName
   1620   )
   1621 {
   1622   FILE    *Fptr;
   1623   INT8    Line[MAX_LINE_LEN];
   1624   UINT32  Guid1H;
   1625   UINT32  Guid1L;
   1626   UINT32  Guid2H;
   1627   UINT32  Guid2L;
   1628   INT8    SymName1[MAX_LINE_LEN];
   1629   INT8    SymName2[MAX_LINE_LEN];
   1630   BOOLEAN Done;
   1631   BOOLEAN LowFirst;
   1632   BOOLEAN FoundLow;
   1633 
   1634   if ((Fptr = fopen (FileName, "r")) == NULL) {
   1635     Error (NULL, 0, 0, FileName, "could not open input file for reading");
   1636     return STATUS_ERROR;
   1637   }
   1638 
   1639   Done = FALSE;
   1640   if (fgets (Line, sizeof (Line), Fptr) == NULL) {
   1641     Done = 1;
   1642   }
   1643   //
   1644   // Read lines from the file until done. Since the guid definition takes
   1645   // two lines, we read lines in different places to recover gracefully
   1646   // from mismatches. For example, if you thought you found the first half,
   1647   // but the next line had a symbol mismatch, then you have to process the
   1648   // line again in case it's the start of a new definition.
   1649   //
   1650   while (!Done) {
   1651     //
   1652     // Check current line for GUID definition. Assume low define first.
   1653     //
   1654     if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) {
   1655       //
   1656       // Might have to swap guids later. Save off if we found the LOW first
   1657       //
   1658       if (FoundLow) {
   1659         LowFirst = TRUE;
   1660       } else {
   1661         LowFirst = FALSE;
   1662       }
   1663       //
   1664       // Read the next line and try for the rest of the guid definition
   1665       //
   1666       if (fgets (Line, sizeof (Line), Fptr) == NULL) {
   1667         Done = 1;
   1668       } else {
   1669         if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) {
   1670           //
   1671           // Found another. If the symbol names match, then save it off.
   1672           //
   1673           if (strcmp (SymName1, SymName2) == 0) {
   1674             //
   1675             // Yea, found one. Save it off.
   1676             //
   1677             if (LowFirst) {
   1678               AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L, SymName1);
   1679             } else {
   1680               AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L, SymName1);
   1681             }
   1682             //
   1683             // Read the next line for processing
   1684             //
   1685             if (fgets (Line, sizeof (Line), Fptr) == NULL) {
   1686               Done = 1;
   1687             }
   1688           } else {
   1689             //
   1690             // Don't get another line so that we reprocess this line in case it
   1691             // contains the start of a new definition.
   1692             // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n",
   1693             //    FileName, SymName1, SymName2);
   1694             //
   1695           }
   1696         } else {
   1697           //
   1698           // Second line was not a guid definition. Get the next line from the
   1699           // file.
   1700           //
   1701           if (fgets (Line, sizeof (Line), Fptr) == NULL) {
   1702             Done = 1;
   1703           }
   1704         }
   1705       }
   1706     } else {
   1707       //
   1708       // Not a guid define line. Next.
   1709       //
   1710       if (fgets (Line, sizeof (Line), Fptr) == NULL) {
   1711         Done = 1;
   1712       }
   1713     }
   1714   }
   1715 
   1716   fclose (Fptr);
   1717   return STATUS_SUCCESS;
   1718 }
   1719 //
   1720 // Given a line from an Itanium-based assembly file, check the line for a guid
   1721 // defininition. One of either:
   1722 // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
   1723 // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
   1724 // Return the defined value as two 32-bit values, and whether it's a high
   1725 // or low guid.
   1726 //
   1727 static
   1728 BOOLEAN
   1729 IsIA64GuidLine (
   1730   INT8      *Line,
   1731   UINT32    *GuidHigh,
   1732   UINT32    *GuidLow,
   1733   BOOLEAN   *FoundLow,
   1734   INT8      *SymName
   1735   )
   1736 {
   1737   INT8    *Cptr;
   1738   INT8    CSave;
   1739   INT8    *CSavePtr;
   1740   INT8    *SymStart;
   1741   UINT32  Len;
   1742 
   1743   Cptr = Line;
   1744   Cptr += SkipWhiteSpace (Cptr);
   1745   //
   1746   // look for #define xxxGUID[L|H] 0xHexValue
   1747   //
   1748   if (*Cptr == '#') {
   1749     Cptr++;
   1750     Cptr += SkipWhiteSpace (Cptr);
   1751     //
   1752     // Look for "define"
   1753     //
   1754     if (!strncmp (Cptr, "define", 6)) {
   1755       Cptr += 6;
   1756       //
   1757       // Better be whitespace
   1758       //
   1759       Len = SkipWhiteSpace (Cptr);
   1760       if (Len) {
   1761         Cptr += Len;
   1762         //
   1763         // See if it's a valid symbol name
   1764         //
   1765         Len = ValidSymbolName (Cptr);
   1766         if (Len) {
   1767           //
   1768           // Save the start so we can copy it to their string if later checks are ok
   1769           //
   1770           SymStart = Cptr;
   1771           //
   1772           // It is a valid symbol name, look for the string GuidL or GuidH
   1773           //
   1774           CSavePtr  = Cptr + Len;
   1775           CSave     = *CSavePtr;
   1776           *CSavePtr = 0;
   1777           while (*Cptr) {
   1778             if (strncmp (Cptr, "GuidL", 5) == 0) {
   1779               *FoundLow = 1;
   1780               break;
   1781             } else if (strncmp (Cptr, "GuidH", 5) == 0) {
   1782               *FoundLow = 0;
   1783               break;
   1784             }
   1785 
   1786             Cptr++;
   1787           }
   1788           //
   1789           // If we didn't run out of string, then we found the GUID string.
   1790           // Restore the null character we inserted above and continue.
   1791           // Now look for  0x.......
   1792           //
   1793           if (*Cptr) {
   1794             //
   1795             // Return symbol name less the "L" or "H"
   1796             //
   1797             strcpy (SymName, SymStart);
   1798             SymName[strlen (SymName) - 1] = 0;
   1799             Cptr                          = CSavePtr;
   1800             *CSavePtr                     = CSave;
   1801             Cptr += SkipWhiteSpace (Cptr);
   1802             if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) {
   1803               //
   1804               // skip over "0x"
   1805               //
   1806               Cptr += 2;
   1807               //
   1808               // 0x0123456789ABCDEF -- null terminate after 8 characters,
   1809               // scan, replace the character and scan at that point.
   1810               //
   1811               CSave       = *(Cptr + 8);
   1812               *(Cptr + 8) = 0;
   1813               if (sscanf (Cptr, "%X", GuidHigh) == 1) {
   1814                 *(Cptr + 8) = CSave;
   1815                 if (sscanf (Cptr + 8, "%X", GuidLow) == 1) {
   1816                   return TRUE;
   1817                 }
   1818               }
   1819             }
   1820           }
   1821         }
   1822       }
   1823     }
   1824   }
   1825 
   1826   return FALSE;
   1827 }
   1828 //
   1829 // Look at the characters in the string and determine if it's a valid
   1830 // symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]*
   1831 //
   1832 static
   1833 UINT32
   1834 ValidSymbolName (
   1835   INT8    *Name
   1836   )
   1837 {
   1838   int Len;
   1839 
   1840   Len = 0;
   1841 
   1842   //
   1843   // Test first character
   1844   //
   1845   if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) {
   1846     Name++;
   1847     Len = 1;
   1848     while (*Name) {
   1849       if (((*Name >= 'a') && (*Name <= 'z')) ||
   1850           ((*Name >= 'A') && (*Name <= 'Z')) ||
   1851           ((*Name >= '0') && (*Name <= '9')) ||
   1852           (*Name == '_')
   1853           ) {
   1854         Name++;
   1855         Len++;
   1856       } else {
   1857         break;
   1858       }
   1859     }
   1860   }
   1861 
   1862   return Len;
   1863 }
   1864 
   1865 static
   1866 UINT32
   1867 SkipWhiteSpace (
   1868   INT8    *Str
   1869   )
   1870 {
   1871   UINT32  Len;
   1872   Len = 0;
   1873   while (isspace (*Str) && *Str) {
   1874     Len++;
   1875     Str++;
   1876   }
   1877 
   1878   return Len;
   1879 }
   1880 //
   1881 // found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
   1882 //
   1883 static
   1884 STATUS
   1885 AddPkgGuid (
   1886   INT8      *FileName,
   1887   UINT32    *Data,
   1888   UINT64    *Data64
   1889   )
   1890 {
   1891   GUID_RECORD *NewRec;
   1892   int         Index;
   1893 
   1894   //
   1895   // Sanity check the data
   1896   //
   1897   if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) {
   1898     Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL);
   1899     return STATUS_ERROR;
   1900   }
   1901   //
   1902   // More checks for Data64?
   1903   // Allocate memory for a new one guid structure
   1904   //
   1905   NewRec = malloc (sizeof (GUID_RECORD));
   1906   if (NewRec == NULL) {
   1907     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1908     return STATUS_ERROR;
   1909   }
   1910 
   1911   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
   1912   NewRec->FileName = malloc (strlen (FileName) + 1);
   1913   if (NewRec->FileName == NULL) {
   1914     free (NewRec);
   1915     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1916     return STATUS_ERROR;
   1917   }
   1918 
   1919   strcpy (NewRec->FileName, FileName);
   1920   NewRec->Guid.Data1    = Data[0];
   1921   NewRec->Guid.Data2    = (UINT16) Data[1];
   1922   NewRec->Guid.Data3    = (UINT16) Data[2];
   1923   NewRec->Guid.Data4[0] = (UINT8) (Data[3] >> 8);
   1924   NewRec->Guid.Data4[1] = (UINT8) Data[3];
   1925   for (Index = 2; Index < 8; Index++) {
   1926     NewRec->Guid.Data4[Index] = ((UINT8*)Data64)[7-Index];
   1927   }
   1928   //
   1929   // Add it to the list
   1930   //
   1931   NewRec->Next  = gGuidList;
   1932   gGuidList     = NewRec;
   1933 
   1934   //
   1935   // Report it
   1936   // ReportGuid (FileName, NewRec);
   1937   //
   1938   return STATUS_SUCCESS;
   1939 }
   1940 //
   1941 // Add a guid consisting of 11 fields to our list of guids
   1942 //
   1943 static
   1944 STATUS
   1945 AddGuid11 (
   1946   INT8      *FileName,
   1947   UINT32    *Data,
   1948   INT8      *SymName
   1949   )
   1950 {
   1951   GUID_RECORD *NewRec;
   1952   int         Index;
   1953 
   1954   //
   1955   // Sanity check the data
   1956   //
   1957   if (!CheckGuidData (Data, 11)) {
   1958     return STATUS_ERROR;
   1959   }
   1960   //
   1961   // Allocate memory for a new one guid structure
   1962   //
   1963   NewRec = malloc (sizeof (GUID_RECORD));
   1964   if (NewRec == NULL) {
   1965     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1966     return STATUS_ERROR;
   1967   }
   1968 
   1969   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
   1970   NewRec->FileName = malloc (strlen (FileName) + 1);
   1971   if (NewRec->FileName == NULL) {
   1972     free (NewRec);
   1973     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1974     return STATUS_ERROR;
   1975   }
   1976 
   1977   strcpy (NewRec->FileName, FileName);
   1978   if (SymName != NULL) {
   1979     NewRec->SymName = malloc (strlen (SymName) + 1);
   1980     if (NewRec->SymName == NULL) {
   1981       free (NewRec);
   1982       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1983       return STATUS_ERROR;
   1984     }
   1985     strcpy (NewRec->SymName, SymName);
   1986   }
   1987 
   1988   NewRec->Guid.Data1  = Data[0];
   1989   NewRec->Guid.Data2  = (UINT16) Data[1];
   1990   NewRec->Guid.Data3  = (UINT16) Data[2];
   1991   for (Index = 0; Index < 8; Index++) {
   1992     NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index];
   1993   }
   1994   //
   1995   // Add it to the list
   1996   //
   1997   NewRec->Next  = gGuidList;
   1998   gGuidList     = NewRec;
   1999 
   2000   //
   2001   // Report it
   2002   // ReportGuid (FileName, NewRec);
   2003   //
   2004   return STATUS_SUCCESS;
   2005 }
   2006 //
   2007 // For debug purposes, print each guid found
   2008 //
   2009 // static
   2010 // VOID
   2011 // ReportGuid (
   2012 //  INT8        *FileName,
   2013 // GUID_RECORD *NewGuid
   2014 //  )
   2015 // {
   2016 //  //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1);
   2017 // }
   2018 //
   2019 // Free up memory we allocated to keep track of guids defined.
   2020 //
   2021 static
   2022 VOID
   2023 FreeGuids (
   2024   VOID
   2025   )
   2026 {
   2027   GUID_RECORD *NextRec;
   2028   while (gGuidList != NULL) {
   2029     NextRec = gGuidList->Next;
   2030     if (gGuidList->FileName != NULL) {
   2031       free (gGuidList->FileName);
   2032     }
   2033 
   2034     if (gGuidList->SymName != NULL) {
   2035       free (gGuidList->SymName);
   2036     }
   2037 
   2038     free (gGuidList);
   2039     gGuidList = NextRec;
   2040   }
   2041 }
   2042 
   2043 static
   2044 VOID
   2045 FreeSigs (
   2046   VOID
   2047   )
   2048 {
   2049   SIGNATURE_RECORD  *NextRec;
   2050   while (gSignatureList != NULL) {
   2051     NextRec = gSignatureList->Next;
   2052     if (gSignatureList->FileName != NULL) {
   2053       free (gSignatureList->FileName);
   2054     }
   2055 
   2056     free (gSignatureList);
   2057     gSignatureList = NextRec;
   2058   }
   2059 }
   2060 //
   2061 // Scan through all guids defined and compare each for duplicates.
   2062 //
   2063 static
   2064 STATUS
   2065 CheckDuplicates (
   2066   VOID
   2067   )
   2068 {
   2069   GUID_RECORD       *CurrentFile;
   2070 
   2071   GUID_RECORD       *TempFile;
   2072   SIGNATURE_RECORD  *CurrentSig;
   2073   SIGNATURE_RECORD  *TempSig;
   2074   STATUS            Status;
   2075   int               Index;
   2076   int               DupCount;
   2077   int               Len;
   2078   BOOLEAN           Same;
   2079   UINT32            GuidSum;
   2080   INT8              *SymName;
   2081 
   2082   Status = STATUS_SUCCESS;
   2083 
   2084   //
   2085   // If we're checking guids.....
   2086   //
   2087   if (gOptions.CheckGuids) {
   2088     //
   2089     // If -p option, print all guids found
   2090     //
   2091     if (gOptions.PrintFound) {
   2092       CurrentFile = gGuidList;
   2093       while (CurrentFile != NULL) {
   2094         fprintf (
   2095           stdout,
   2096           "GUID:  0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n",
   2097           (UINT32) CurrentFile->Guid.Data1,
   2098           (UINT32) CurrentFile->Guid.Data2,
   2099           (UINT32) CurrentFile->Guid.Data3,
   2100           (UINT32) CurrentFile->Guid.Data4[0],
   2101           (UINT32) CurrentFile->Guid.Data4[1],
   2102           (UINT32) CurrentFile->Guid.Data4[2],
   2103           (UINT32) CurrentFile->Guid.Data4[3],
   2104           (UINT32) CurrentFile->Guid.Data4[4],
   2105           (UINT32) CurrentFile->Guid.Data4[5],
   2106           (UINT32) CurrentFile->Guid.Data4[6],
   2107           (UINT32) CurrentFile->Guid.Data4[7],
   2108           CurrentFile->FileName
   2109           );
   2110         CurrentFile = CurrentFile->Next;
   2111       }
   2112     }
   2113 
   2114     if (gOptions.GuidXReference) {
   2115       CurrentFile = gGuidList;
   2116       while (CurrentFile != NULL) {
   2117         //
   2118         // If no symbol name, print FileName
   2119         //
   2120         SymName = CurrentFile->SymName;
   2121         if (SymName == NULL) {
   2122           //
   2123           // Assume file name will not be NULL and strlen > 0
   2124           //
   2125           SymName = CurrentFile->FileName + strlen (CurrentFile->FileName) - 1;
   2126           while ((*SymName != '\\') && (SymName > CurrentFile->FileName)) SymName --;
   2127           if (*SymName == '\\') SymName ++;
   2128         }
   2129 
   2130         fprintf (
   2131           stdout,
   2132           "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n",
   2133           (UINT32) CurrentFile->Guid.Data1,
   2134           (UINT32) CurrentFile->Guid.Data2,
   2135           (UINT32) CurrentFile->Guid.Data3,
   2136           (UINT32) CurrentFile->Guid.Data4[0],
   2137           (UINT32) CurrentFile->Guid.Data4[1],
   2138           (UINT32) CurrentFile->Guid.Data4[2],
   2139           (UINT32) CurrentFile->Guid.Data4[3],
   2140           (UINT32) CurrentFile->Guid.Data4[4],
   2141           (UINT32) CurrentFile->Guid.Data4[5],
   2142           (UINT32) CurrentFile->Guid.Data4[6],
   2143           (UINT32) CurrentFile->Guid.Data4[7],
   2144           SymName
   2145           );
   2146         CurrentFile = CurrentFile->Next;
   2147       }
   2148     }
   2149     //
   2150     // Now go through all guids and report duplicates.
   2151     //
   2152     CurrentFile = gGuidList;
   2153     while (CurrentFile != NULL) {
   2154       DupCount  = 0;
   2155       TempFile  = CurrentFile->Next;
   2156       while (TempFile) {
   2157         //
   2158         // Compare the guids
   2159         //
   2160         if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) &&
   2161             (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) &&
   2162             (CurrentFile->Guid.Data3 == TempFile->Guid.Data3)
   2163             ) {
   2164           //
   2165           // OR in all the guid bytes so we can ignore NULL-guid definitions.
   2166           //
   2167           GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3;
   2168           Same    = TRUE;
   2169           for (Index = 0; Index < 8; Index++) {
   2170             GuidSum |= CurrentFile->Guid.Data4[Index];
   2171             if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) {
   2172               Same = FALSE;
   2173               break;
   2174             }
   2175           }
   2176           //
   2177           // If they're the same, and the guid was non-zero, print a message.
   2178           //
   2179           if (Same && GuidSum) {
   2180             if (DupCount == 0) {
   2181               Error (NULL, 0, 0, "duplicate GUIDS found", NULL);
   2182               fprintf (stdout, "   FILE1: %s\n", CurrentFile->FileName);
   2183             }
   2184 
   2185             DupCount++;
   2186             fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempFile->FileName);
   2187             //
   2188             // Flag it as reported so we don't report it again if there's three or more
   2189             //
   2190             TempFile->Reported = TRUE;
   2191           }
   2192         }
   2193         //
   2194         // Next one
   2195         //
   2196         TempFile = TempFile->Next;
   2197       }
   2198       //
   2199       // Print the guid if we found duplicates
   2200       //
   2201       if (DupCount) {
   2202         fprintf (
   2203           stdout,
   2204           "   GUID:  0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
   2205           (UINT32) CurrentFile->Guid.Data1,
   2206           (UINT32) CurrentFile->Guid.Data2,
   2207           (UINT32) CurrentFile->Guid.Data3,
   2208           (UINT32) CurrentFile->Guid.Data4[0],
   2209           (UINT32) CurrentFile->Guid.Data4[1],
   2210           (UINT32) CurrentFile->Guid.Data4[2],
   2211           (UINT32) CurrentFile->Guid.Data4[3],
   2212           (UINT32) CurrentFile->Guid.Data4[4],
   2213           (UINT32) CurrentFile->Guid.Data4[5],
   2214           (UINT32) CurrentFile->Guid.Data4[6],
   2215           (UINT32) CurrentFile->Guid.Data4[7]
   2216           );
   2217         //
   2218         // return STATUS_ERROR;
   2219         //
   2220       }
   2221       //
   2222       // Find the next one that hasn't been reported
   2223       //
   2224       do {
   2225         CurrentFile = CurrentFile->Next;
   2226       } while ((CurrentFile != NULL) && (CurrentFile->Reported));
   2227     }
   2228   }
   2229 
   2230   if (gOptions.CheckSignatures) {
   2231     //
   2232     // Print ones found if specified
   2233     //
   2234     if (gOptions.PrintFound) {
   2235       CurrentSig = gSignatureList;
   2236       while (CurrentSig != NULL) {
   2237         Len = CurrentSig->Signature.DataLen;
   2238         for (Index = 0; Index < Len; Index++) {
   2239           fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
   2240         }
   2241 
   2242         fprintf (stdout, "  %s\n", CurrentSig->FileName);
   2243         CurrentSig = CurrentSig->Next;
   2244       }
   2245     }
   2246 
   2247     CurrentSig = gSignatureList;
   2248     while (CurrentSig != NULL) {
   2249       DupCount  = 0;
   2250       TempSig   = CurrentSig->Next;
   2251       Len       = CurrentSig->Signature.DataLen;
   2252       while (TempSig) {
   2253         //
   2254         // Check for same length, then do string compare
   2255         //
   2256         if (Len == TempSig->Signature.DataLen) {
   2257           if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) {
   2258             //
   2259             // Print header message if first failure for this sig
   2260             //
   2261             if (DupCount == 0) {
   2262               Error (NULL, 0, 0, "duplicate signatures found", NULL);
   2263               fprintf (stdout, "   FILE1: %s\n", CurrentSig->FileName);
   2264             }
   2265 
   2266             DupCount++;
   2267             fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempSig->FileName);
   2268             TempSig->Reported = TRUE;
   2269           }
   2270         }
   2271 
   2272         TempSig = TempSig->Next;
   2273       }
   2274 
   2275       if (DupCount) {
   2276         fprintf (stdout, "   SIG:   ");
   2277         for (Index = 0; Index < Len; Index++) {
   2278           fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
   2279         }
   2280 
   2281         fprintf (stdout, "\n");
   2282       }
   2283       //
   2284       // On to the next one that hasn't been reported
   2285       //
   2286       do {
   2287         CurrentSig = CurrentSig->Next;
   2288       } while ((CurrentSig != NULL) && (CurrentSig->Reported));
   2289     }
   2290   }
   2291 
   2292   return Status;
   2293 }
   2294 
   2295 static
   2296 VOID
   2297 FreeOptions (
   2298   VOID
   2299   )
   2300 /*++
   2301 
   2302 Routine Description:
   2303   Free up any memory we allocated when processing command-line options.
   2304 
   2305 Arguments:
   2306   None.
   2307 
   2308 Returns:
   2309   NA
   2310 
   2311 Notes:
   2312   We don't free up the ->Str fields because we did not allocate them.
   2313   Instead, we just set the pointer to point to the actual parameter
   2314   from the command line.
   2315 
   2316 --*/
   2317 {
   2318   STRING_LIST *Ptr;
   2319   while (gOptions.ExcludeDirs != NULL) {
   2320     Ptr = gOptions.ExcludeDirs->Next;
   2321     //
   2322     // free (gOptions.ExcludeDirs->Str);
   2323     //
   2324     free (gOptions.ExcludeDirs);
   2325     gOptions.ExcludeDirs = Ptr;
   2326   }
   2327 
   2328   while (gOptions.ExcludeSubDirs != NULL) {
   2329     Ptr = gOptions.ExcludeSubDirs->Next;
   2330     //
   2331     // free (gOptions.ExcludeSubDirs->Str);
   2332     //
   2333     free (gOptions.ExcludeSubDirs);
   2334     gOptions.ExcludeSubDirs = Ptr;
   2335   }
   2336 
   2337   while (gOptions.ExcludeExtensions != NULL) {
   2338     Ptr = gOptions.ExcludeExtensions->Next;
   2339     //
   2340     // free (gOptions.ExcludeExtensions->Str);
   2341     //
   2342     free (gOptions.ExcludeExtensions);
   2343     gOptions.ExcludeExtensions = Ptr;
   2344   }
   2345 
   2346   while (gOptions.ExcludeFiles != NULL) {
   2347     Ptr = gOptions.ExcludeFiles->Next;
   2348     //
   2349     // free (gOptions.ExcludeFiles->Str);
   2350     //
   2351     free (gOptions.ExcludeFiles);
   2352     gOptions.ExcludeFiles = Ptr;
   2353   }
   2354 }
   2355 //
   2356 // Given an array of 32-bit data, validate the data for the given number of
   2357 // guid data. For example, it might have been scanned as 16 bytes of data, or
   2358 // 11 fields of data.
   2359 //
   2360 static
   2361 BOOLEAN
   2362 CheckGuidData (
   2363   UINT32    *Data,
   2364   UINT32    DataCount
   2365   )
   2366 {
   2367   UINT32  Index;
   2368 
   2369   if (DataCount == 16) {
   2370     for (Index = 0; Index < 16; Index++) {
   2371       if (Data[Index] &~0xFF) {
   2372         return FALSE;
   2373       }
   2374     }
   2375 
   2376     return TRUE;
   2377   } else if (DataCount == 11) {
   2378     //
   2379     // Data[0] never out of range (32-bit)
   2380     //
   2381     if ((Data[1] | Data[2]) &~0xFFFF) {
   2382       //
   2383       // Error ("Out of range value for GUID data word(s) [1] and/or [2]");
   2384       //
   2385       return FALSE;
   2386     }
   2387 
   2388     for (Index = 0; Index < 8; Index++) {
   2389       if (Data[Index + 3] &~0xFF) {
   2390         //
   2391         // Error ("Out of range value for GUID data byte(s) [4] - [11]");
   2392         //
   2393         return FALSE;
   2394       }
   2395     }
   2396 
   2397     return TRUE;
   2398   }
   2399 
   2400   return FALSE;
   2401 }
   2402 
   2403 static
   2404 VOID
   2405 ConcatenateLines (
   2406   FILE        *Fptr,
   2407   INT8        *Line,
   2408   UINT32      Len
   2409   )
   2410 {
   2411   UINT32      LineLen;
   2412   BOOLEAN     NeedCheck;
   2413 
   2414   NeedCheck = TRUE;
   2415   while (NeedCheck) {
   2416     LineLen = strlen (Line);
   2417     if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
   2418       Line[LineLen - 2] = '\0';
   2419       fgets (Line + LineLen - 2, Len - LineLen, Fptr);
   2420     } else if (Line[LineLen - 1] == '\\') {
   2421       Line[LineLen - 1] = '\0';
   2422       fgets (Line + LineLen - 1, Len - LineLen, Fptr);
   2423     } else {
   2424       NeedCheck = FALSE;
   2425     }
   2426   }
   2427 }
   2428