mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 11:23:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2401 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2401 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2004 - 2007, Intel Corporation                                                         
 | |
| All rights reserved. This program and the accompanying materials                          
 | |
| are licensed and made available under the terms and conditions of the BSD License         
 | |
| which accompanies this distribution.  The full text of the license may be found at        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| Module Name:  
 | |
| 
 | |
|   GuidChk.c 
 | |
|   
 | |
| Abstract:
 | |
| 
 | |
|   Parse files in a directory and subdirectories to find all guid definitions.
 | |
|   Then check them against each other to make sure there are no duplicates.
 | |
|   
 | |
| --*/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| 
 | |
| #include "CommonUtils.h"
 | |
| #include "FileSearch.h"
 | |
| #include "UtilsMsgs.h"
 | |
| 
 | |
| #define MAX_LINE_LEN  180 // we concatenate two lines sometimes
 | |
| // Define a structure that correlates filename extensions to an enumerated
 | |
| // type.
 | |
| //
 | |
| 
 | |
| #define UTILITY_NAME              "GuidChk"
 | |
| #define UTILITY_MAJOR_VERSION     1
 | |
| #define UTILITY_MINOR_VERSION     0
 | |
| 
 | |
| typedef struct {
 | |
|   INT8  *Extension;
 | |
|   INT8  ExtensionCode;
 | |
| } FILE_TYPE_TABLE_ENTRY;
 | |
| 
 | |
| #define FILE_EXTENSION_UNKNOWN  0
 | |
| #define FILE_EXTENSION_C        1
 | |
| #define FILE_EXTENSION_H        2
 | |
| #define FILE_EXTENSION_IA32_ASM 3
 | |
| #define FILE_EXTENSION_IA32_INC 4
 | |
| #define FILE_EXTENSION_IA64_ASM 5
 | |
| #define FILE_EXTENSION_IA64_INC 6
 | |
| #define FILE_EXTENSION_PKG      7
 | |
| #define FILE_EXTENSION_INF      8
 | |
| 
 | |
| FILE_TYPE_TABLE_ENTRY FileTypeTable[] = {
 | |
|   ".c",
 | |
|   FILE_EXTENSION_C,
 | |
|   ".h",
 | |
|   FILE_EXTENSION_H,
 | |
|   ".inc",
 | |
|   FILE_EXTENSION_IA32_INC,
 | |
|   ".asm",
 | |
|   FILE_EXTENSION_IA32_ASM,
 | |
|   ".s",
 | |
|   FILE_EXTENSION_IA64_ASM,
 | |
|   ".pkg",
 | |
|   FILE_EXTENSION_PKG,
 | |
|   ".inf",
 | |
|   FILE_EXTENSION_INF,
 | |
|   ".i",
 | |
|   FILE_EXTENSION_IA64_INC,
 | |
|   NULL,
 | |
|   0
 | |
| };
 | |
| 
 | |
| typedef struct EFI_GUID {
 | |
|   UINT32  Data1;
 | |
|   UINT16  Data2;
 | |
|   UINT16  Data3;
 | |
|   UINT8   Data4[8];
 | |
| } EFI_GUID;
 | |
| 
 | |
| typedef struct {
 | |
|   INT8  Data[4];
 | |
|   INT8  DataLen;
 | |
| } EFI_SIGNATURE;
 | |
| 
 | |
| typedef struct _GUID_RECORD {
 | |
|   struct _GUID_RECORD *Next;
 | |
|   BOOLEAN             Reported;
 | |
|   INT8                *FileName;
 | |
|   INT8                *SymName;
 | |
|   EFI_GUID            Guid;
 | |
| } GUID_RECORD;
 | |
| 
 | |
| typedef struct _SIGNATURE_RECORD {
 | |
|   struct _SIGNATURE_RECORD  *Next;
 | |
|   BOOLEAN                   Reported;
 | |
|   INT8                      *FileName;
 | |
|   EFI_SIGNATURE             Signature;
 | |
| } SIGNATURE_RECORD;
 | |
| 
 | |
| //
 | |
| // Utility options
 | |
| //
 | |
| typedef struct {
 | |
|   INT8        DatabaseOutputFileName[MAX_PATH]; // with -b option
 | |
|   STRING_LIST *ExcludeDirs;                     // list of directory names not to process
 | |
|   STRING_LIST *ExcludeSubDirs;                  // list of directory names to not process subdirectories (build)
 | |
|   STRING_LIST *ExcludeFiles;                    // list of files to exclude (make.inf)
 | |
|   STRING_LIST *ExcludeExtensions;               // list of filename extensions to exclude (.inf, .pkg)
 | |
|   BOOLEAN     Verbose;
 | |
|   BOOLEAN     PrintFound;
 | |
|   BOOLEAN     CheckGuids;
 | |
|   BOOLEAN     CheckSignatures;
 | |
|   BOOLEAN     GuidXReference;
 | |
| } OPTIONS;
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessArgs (
 | |
|   int     Argc,
 | |
|   char    *Argv[]
 | |
|   );
 | |
| 
 | |
| static
 | |
| VOID
 | |
| Version (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| static
 | |
| VOID
 | |
| Usage (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessDirectory (
 | |
|   INT8        *Path,
 | |
|   INT8        *DirectoryName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessFile (
 | |
|   INT8                *DirectoryName,
 | |
|   INT8                *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| UINT32
 | |
| GetFileExtension (
 | |
|   INT8        *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| UINT32
 | |
| SkipWhiteSpace (
 | |
|   INT8    *Str
 | |
|   );
 | |
| 
 | |
| static
 | |
| UINT32
 | |
| ValidSymbolName (
 | |
|   INT8    *Name
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessCFileGuids (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| AddSignature (
 | |
|   INT8      *FileName,
 | |
|   INT8      *StrDef,
 | |
|   UINT32    SigSize
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessCFileSigs (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessINFFileGuids (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessPkgFileGuids (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessIA32FileGuids (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessIA64FileGuids (
 | |
|   INT8    *FileName
 | |
|   );
 | |
| 
 | |
| static
 | |
| BOOLEAN
 | |
| IsIA64GuidLine (
 | |
|   INT8      *Line,
 | |
|   UINT32    *GuidHigh,
 | |
|   UINT32    *GuidLow,
 | |
|   BOOLEAN   *Low,
 | |
|   INT8      *SymName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| AddGuid11 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data,
 | |
|   INT8      *SymName
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| AddPkgGuid (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data,
 | |
|   UINT64    *Data64
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| AddGuid16 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| AddGuid64x2 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    DataHH,                             // Upper 32-bits of upper 64 bits of guid
 | |
|   UINT32    DataHL,                             // Lower 32-bits of upper 64 bits
 | |
|   UINT32    DataLH,
 | |
|   UINT32    DataLL
 | |
|   );
 | |
| 
 | |
| static
 | |
| VOID
 | |
| FreeGuids (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| static
 | |
| VOID
 | |
| FreeSigs (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| CheckDuplicates (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| //
 | |
| // static
 | |
| // VOID
 | |
| // ReportGuid (
 | |
| //  INT8        *FileName,
 | |
| //  GUID_RECORD *FileRecord
 | |
| //  );
 | |
| //
 | |
| static
 | |
| VOID
 | |
| FreeOptions (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| static
 | |
| BOOLEAN
 | |
| CheckGuidData (
 | |
|   UINT32    *GuidData,
 | |
|   UINT32    DataCount
 | |
|   );
 | |
| 
 | |
| /**************************** GLOBALS ****************************************/
 | |
| static GUID_RECORD      *gGuidList      = NULL;
 | |
| static SIGNATURE_RECORD *gSignatureList = NULL;
 | |
| static OPTIONS          gOptions;
 | |
| 
 | |
| /*****************************************************************************/
 | |
| int
 | |
| main (
 | |
|   int     Argc,
 | |
|   char    *Argv[]
 | |
|   )
 | |
| {
 | |
|   INT8    *Cwd;
 | |
|   STATUS  Status;
 | |
| 
 | |
|   SetUtilityName ("GuidChk");
 | |
|   //
 | |
|   // Get the current working directory and then process the command line
 | |
|   // arguments.
 | |
|   //
 | |
|   Cwd     = _getcwd (NULL, 0);
 | |
|   Status  = ProcessArgs (Argc, Argv);
 | |
|   if (Status != STATUS_SUCCESS) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (gOptions.CheckGuids || gOptions.CheckSignatures) {
 | |
|     Status = ProcessDirectory (Cwd, NULL);
 | |
|     if (Status == STATUS_SUCCESS) {
 | |
|       //
 | |
|       // Check for duplicates
 | |
|       //
 | |
|       Status = CheckDuplicates ();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (gOptions.DatabaseOutputFileName[0] != 0) {
 | |
|     CreateGuidList (gOptions.DatabaseOutputFileName);
 | |
|   }
 | |
|   //
 | |
|   // Free up the memory
 | |
|   //
 | |
|   free (Cwd);
 | |
|   FreeGuids ();
 | |
|   FreeSigs ();
 | |
|   FreeOptions ();
 | |
|   return GetUtilityStatus ();
 | |
| }
 | |
| 
 | |
| static
 | |
| STATUS
 | |
| ProcessArgs (
 | |
|   int     Argc,
 | |
|   char    *Argv[]
 | |
|   )
 | |
| {
 | |
|   STRING_LIST *StrList;
 | |
| 
 | |
|   memset ((char *) &gOptions, 0, sizeof (gOptions));
 | |
|   //
 | |
|   // skip over program name
 | |
|   //
 | |
|   Argc--;
 | |
|   Argv++;
 | |
| 
 | |
|   if (Argc == 0) {
 | |
|     Usage ();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   
 | |
|   if ((strcmp(Argv[0], "-h") == 0) || (strcmp(Argv[0], "--help") == 0) ||
 | |
|       (strcmp(Argv[0], "-?") == 0) || (strcmp(Argv[0], "/?") == 0)) {
 | |
|     Usage();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   
 | |
|   if ((strcmp(Argv[0], "-V") == 0) || (strcmp(Argv[0], "--version") == 0)) {
 | |
|     Version();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|  
 | |
|   while (Argc > 0) {
 | |
|     //
 | |
|     // Look for options
 | |
|     //
 | |
|     if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
 | |
|       switch (Argv[0][1]) {
 | |
|       //
 | |
|       // Help option
 | |
|       //
 | |
|       case 'h':
 | |
|       case 'H':
 | |
|       case '?':
 | |
|         Usage ();
 | |
|         return STATUS_ERROR;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Check guids option
 | |
|       //
 | |
|       case 'g':
 | |
|       case 'G':
 | |
|         gOptions.CheckGuids = TRUE;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Check signatures option
 | |
|       //
 | |
|       case 's':
 | |
|       case 'S':
 | |
|         gOptions.CheckSignatures = TRUE;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Print guids found option
 | |
|       //
 | |
|       case 'p':
 | |
|       case 'P':
 | |
|         gOptions.PrintFound = TRUE;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Exclude files option
 | |
|       //
 | |
|       case 'f':
 | |
|       case 'F':
 | |
|         //
 | |
|         // Check for another arg
 | |
|         //
 | |
|         if (Argc < 2) {
 | |
|           Error (NULL, 0, 0, Argv[0], "missing argument with option");
 | |
|           Usage ();
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         StrList = malloc (sizeof (STRING_LIST));
 | |
|         if (StrList == NULL) {
 | |
|           Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         memset ((char *) StrList, 0, sizeof (STRING_LIST));
 | |
|         StrList->Str          = Argv[1];
 | |
|         StrList->Next         = gOptions.ExcludeFiles;
 | |
|         gOptions.ExcludeFiles = StrList;
 | |
|         Argc--;
 | |
|         Argv++;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Exclude directories option
 | |
|       //
 | |
|       case 'd':
 | |
|       case 'D':
 | |
|         //
 | |
|         // Check for another arg
 | |
|         //
 | |
|         if (Argc < 2) {
 | |
|           Error (NULL, 0, 0, Argv[0], "missing argument with option");
 | |
|           Usage ();
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         StrList = malloc (sizeof (STRING_LIST));
 | |
|         if (StrList == NULL) {
 | |
|           Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         memset ((char *) StrList, 0, sizeof (STRING_LIST));
 | |
|         StrList->Str          = Argv[1];
 | |
|         StrList->Next         = gOptions.ExcludeDirs;
 | |
|         gOptions.ExcludeDirs  = StrList;
 | |
|         Argc--;
 | |
|         Argv++;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // -u  exclude all subdirectories of a given directory option
 | |
|       //
 | |
|       case 'u':
 | |
|       case 'U':
 | |
|         //
 | |
|         // Check for another arg
 | |
|         //
 | |
|         if (Argc < 2) {
 | |
|           Error (NULL, 0, 0, Argv[0], "missing argument with option");
 | |
|           Usage ();
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         StrList = malloc (sizeof (STRING_LIST));
 | |
|         if (StrList == NULL) {
 | |
|           Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         memset ((char *) StrList, 0, sizeof (STRING_LIST));
 | |
|         StrList->Str            = Argv[1];
 | |
|         StrList->Next           = gOptions.ExcludeSubDirs;
 | |
|         gOptions.ExcludeSubDirs = StrList;
 | |
|         Argc--;
 | |
|         Argv++;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // -e  exclude by filename extension option
 | |
|       //
 | |
|       case 'e':
 | |
|       case 'E':
 | |
|         //
 | |
|         // Check for another arg
 | |
|         //
 | |
|         if (Argc < 2) {
 | |
|           Error (NULL, 0, 0, Argv[0], "missing argument with option");
 | |
|           Usage ();
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         StrList = malloc (sizeof (STRING_LIST));
 | |
|         if (StrList == NULL) {
 | |
|           Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         memset ((char *) StrList, 0, sizeof (STRING_LIST));
 | |
|         //
 | |
|         // Let them put a * in front of the filename extension
 | |
|         //
 | |
|         StrList->Str = Argv[1];
 | |
|         if (StrList->Str[0] == '*') {
 | |
|           StrList->Str++;
 | |
|         }
 | |
| 
 | |
|         StrList->Next               = gOptions.ExcludeExtensions;
 | |
|         gOptions.ExcludeExtensions  = StrList;
 | |
|         Argc--;
 | |
|         Argv++;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Print guid with matching symbol name for guid definitions found
 | |
|       //
 | |
|       case 'x':
 | |
|       case 'X':
 | |
|         gOptions.GuidXReference = 1;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // -b   Print the internal database list to a file
 | |
|       //
 | |
|       case 'b':
 | |
|       case 'B':
 | |
|         //
 | |
|         // Check for one more arg
 | |
|         //
 | |
|         if (Argc < 2) {
 | |
|           Error (NULL, 0, 0, Argv[0], "must specify file name with option");
 | |
|           Usage ();
 | |
|           return STATUS_ERROR;
 | |
|         }
 | |
| 
 | |
|         strcpy (gOptions.DatabaseOutputFileName, Argv[1]);
 | |
|         Argc--;
 | |
|         Argv++;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         Error (NULL, 0, 0, Argv[0], "invalid option");
 | |
|         Usage ();
 | |
|         return STATUS_ERROR;
 | |
|       }
 | |
|     } else {
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // Next arg
 | |
|     //
 | |
|     Argc--;
 | |
|     Argv++;
 | |
|   }
 | |
| 
 | |
|   if (Argc > 0) {
 | |
|     Error (NULL, 0, 0, Argv[0], "invalid argument");
 | |
|     Usage ();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Have to check signatures, GUIDs, or dump the GUID database.
 | |
|   //
 | |
|   if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) {
 | |
|     Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b");
 | |
|     Usage ();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| 
 | |
| static
 | |
| void 
 | |
| Version(
 | |
|   void
 | |
| )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Displays the standard utility information to SDTOUT
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   printf ("%s v%d.%d -Utility for checking guid duplication for files in a given directory.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
 | |
|   printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
 | |
| }
 | |
| 
 | |
| //
 | |
| // Print usage instructions
 | |
| //
 | |
| static
 | |
| VOID
 | |
| Usage (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   int   Index;
 | |
|   char  *Str[] = {
 | |
|     "GuidChk - scan files for duplicate GUID or signature definitions",
 | |
|     "",
 | |
|     "Usage:  GuidChk {options}\n",
 | |
|     "  Options: ",
 | |
|     "    -d dirname      exclude searching of a directory",
 | |
|     "    -f filename     exclude searching of a file",
 | |
|     "    -e extension    exclude searching of files by extension",
 | |
|     "    -p              print all GUIDS found",
 | |
|     "    -g              check for duplicate guids",
 | |
|     "    -s              check for duplicate signatures",
 | |
|     "    -x              print guid+defined symbol name",
 | |
|     "    -b outfile      write internal GUID+basename list to outfile",
 | |
|     "    -u dirname      exclude searching all subdirectories of a directory",
 | |
|     "    -h,--help,-?,/? display help messages",
 | |
|     "    -V,--version    display version information",
 | |
|     " ",
 | |
|     "   Example: GuidChk -g -u build -d fv -f make.inf -e .pkg",
 | |
|     "",
 | |
|     NULL
 | |
|   };
 | |
|   
 | |
|   Version();
 | |
|   
 | |
|   for (Index = 0; Str[Index] != NULL; Index++) {
 | |
|     fprintf (stdout, "%s\n", Str[Index]);
 | |
|   }
 | |
| }
 | |
| //
 | |
| // Process an entire directory by name
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessDirectory (
 | |
|   INT8          *Path,
 | |
|   INT8          *DirectoryName
 | |
|   )
 | |
| {
 | |
|   FILE_SEARCH_DATA  FSData;
 | |
|   char              *FileMask;
 | |
|   BOOLEAN           Done;
 | |
|   UINT32            Len;
 | |
|   BOOLEAN           NoSubdirs;
 | |
|   STRING_LIST       *SLPtr;
 | |
| 
 | |
|   //
 | |
|   // Root directory may be null
 | |
|   //
 | |
|   if (DirectoryName != NULL) {
 | |
|     //
 | |
|     // printf ("Processing directory: %s\n", DirectoryName);
 | |
|     //
 | |
|   }
 | |
|   //
 | |
|   // Initialize our file searching
 | |
|   //
 | |
|   FileSearchInit (&FSData);
 | |
| 
 | |
|   //
 | |
|   // Exclude some directories, files, and extensions
 | |
|   //
 | |
|   FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs);
 | |
|   FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions);
 | |
|   FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles);
 | |
|   //
 | |
|   // See if this directory is in the list of directories that they
 | |
|   // don't want to process subdirectories of
 | |
|   //
 | |
|   NoSubdirs = FALSE;
 | |
|   if (DirectoryName != NULL) {
 | |
|     for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) {
 | |
|       if (stricmp (SLPtr->Str, DirectoryName) == 0) {
 | |
|         //
 | |
|         // printf ("not processing subdirectories of %s\n", DirectoryName);
 | |
|         //
 | |
|         NoSubdirs = TRUE;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Create a filemask of files to search for. We'll append "\*.*" on the
 | |
|   // end, so allocate some extra bytes.
 | |
|   //
 | |
|   Len = strlen (Path) + 10;
 | |
|   if (DirectoryName != NULL) {
 | |
|     Len += strlen (DirectoryName);
 | |
|   }
 | |
| 
 | |
|   FileMask = malloc (Len);
 | |
|   if (FileMask == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Now put it all together
 | |
|   //
 | |
|   strcpy (FileMask, Path);
 | |
|   if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) {
 | |
|     strcat (FileMask, "\\");
 | |
|     strcat (FileMask, DirectoryName);
 | |
|   }
 | |
| 
 | |
|   strcat (FileMask, "\\*.*");
 | |
| 
 | |
|   //
 | |
|   // Start file searching for files and directories
 | |
|   //
 | |
|   FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR);
 | |
| 
 | |
|   //
 | |
|   // Now hack the "\*.*" off the end of the filemask so we can use it to pass
 | |
|   // the full directory path on recursive calls to process directories.
 | |
|   //
 | |
|   FileMask[strlen (FileMask) - 4] = 0;
 | |
| 
 | |
|   //
 | |
|   // Loop until no more files
 | |
|   //
 | |
|   Done = FALSE;
 | |
|   while (!Done) {
 | |
|     //
 | |
|     // printf ("Found %s...", FSData.FileName);
 | |
|     //
 | |
|     if (FSData.FileFlags & FILE_SEARCH_DIR) {
 | |
|       //
 | |
|       // printf ("directory\n");
 | |
|       //
 | |
|       if (!NoSubdirs) {
 | |
|         ProcessDirectory (FileMask, FSData.FileName);
 | |
|       }
 | |
|     } else if (FSData.FileFlags & FILE_SEARCH_FILE) {
 | |
|       //
 | |
|       // printf ("file\n");
 | |
|       //
 | |
|       ProcessFile (FileMask, FSData.FileName);
 | |
|     } else {
 | |
|       //
 | |
|       // printf ("unknown\n");
 | |
|       //
 | |
|     }
 | |
| 
 | |
|     if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) {
 | |
|       Done = TRUE;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Free up allocated memory
 | |
|   //
 | |
|   free (FileMask);
 | |
| 
 | |
|   //
 | |
|   // Free up our file searching
 | |
|   //
 | |
|   FileSearchDestroy (&FSData);
 | |
| 
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Process a single file.
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessFile (
 | |
|   INT8                *DirectoryName,
 | |
|   INT8                *FileName
 | |
|   )
 | |
| {
 | |
|   STATUS  Status;
 | |
|   UINT32  FileExtension;
 | |
|   INT8    FullFileName[MAX_PATH];
 | |
| 
 | |
|   Status = STATUS_SUCCESS;
 | |
| 
 | |
|   sprintf (FullFileName, "%s\\%s", DirectoryName, FileName);
 | |
|   //
 | |
|   // printf ("Found file: %s\n", FullFileName);
 | |
|   //
 | |
|   FileExtension = GetFileExtension (FileName);
 | |
| 
 | |
|   //
 | |
|   // Process these for GUID checks
 | |
|   //
 | |
|   if (gOptions.CheckGuids) {
 | |
|     switch (FileExtension) {
 | |
|     case FILE_EXTENSION_C:
 | |
|     case FILE_EXTENSION_H:
 | |
|       Status = ProcessCFileGuids (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     case FILE_EXTENSION_PKG:
 | |
|       Status = ProcessPkgFileGuids (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     case FILE_EXTENSION_IA32_INC:
 | |
|     case FILE_EXTENSION_IA32_ASM:
 | |
|       Status = ProcessIA32FileGuids (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     case FILE_EXTENSION_INF:
 | |
|       Status = ProcessINFFileGuids (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     case FILE_EXTENSION_IA64_INC:
 | |
|     case FILE_EXTENSION_IA64_ASM:
 | |
|       Status = ProcessIA64FileGuids (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       //
 | |
|       // No errors anyway
 | |
|       //
 | |
|       Status = STATUS_SUCCESS;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (gOptions.CheckSignatures) {
 | |
|     switch (FileExtension) {
 | |
|     case FILE_EXTENSION_C:
 | |
|     case FILE_EXTENSION_H:
 | |
|       Status = ProcessCFileSigs (FullFileName);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       //
 | |
|       // No errors anyway
 | |
|       //
 | |
|       Status = STATUS_SUCCESS;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // Return a code indicating the file name extension.
 | |
| //
 | |
| static
 | |
| UINT32
 | |
| GetFileExtension (
 | |
|   INT8        *FileName
 | |
|   )
 | |
| {
 | |
|   INT8  *Extension;
 | |
|   int   Index;
 | |
| 
 | |
|   //
 | |
|   // Look back for a filename extension
 | |
|   //
 | |
|   for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) {
 | |
|     if (*Extension == '.') {
 | |
|       for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) {
 | |
|         if (stricmp (FileTypeTable[Index].Extension, Extension) == 0) {
 | |
|           return FileTypeTable[Index].ExtensionCode;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FILE_TYPE_UNKNOWN;
 | |
| }
 | |
| //
 | |
| // Process a .pkg file.
 | |
| //
 | |
| // Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessPkgFileGuids (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN * 2];
 | |
|   INT8    *Cptr;
 | |
|   INT8    *Cptr2;
 | |
|   UINT32  GuidScan[11];
 | |
|   UINT64  Guid64;
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done
 | |
|   //
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     Cptr = Line;
 | |
|     Cptr += SkipWhiteSpace (Line);
 | |
|     if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) {
 | |
|       Cptr += 12;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       if (*Cptr == '=') {
 | |
|         Cptr++;
 | |
|         Cptr += SkipWhiteSpace (Cptr + 1);
 | |
|         //
 | |
|         // Blank out dashes on the line.
 | |
|         //
 | |
|         for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
 | |
|           if (*Cptr2 == '-') {
 | |
|             *Cptr2 = ' ';
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (sscanf (
 | |
|               Cptr,
 | |
|               "%X %X %X %X %I64X",
 | |
|               &GuidScan[0],
 | |
|               &GuidScan[1],
 | |
|               &GuidScan[2],
 | |
|               &GuidScan[3],
 | |
|               &Guid64
 | |
|               ) == 5) {
 | |
|           AddPkgGuid (FileName, GuidScan, &Guid64);
 | |
|         } else {
 | |
|           DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Process an IA32 assembly file.
 | |
| //
 | |
| // Look for:
 | |
| // FIND_FD_GUID_VAL equ  01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h
 | |
| // PEI_GUID_FileNameGuid_Gmch815  equ  081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessIA32FileGuids (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN];
 | |
|   INT8    *Cptr;
 | |
|   INT8    CSave;
 | |
|   INT8    *CSavePtr;
 | |
|   UINT32  Len;
 | |
|   UINT32  GuidData[16];
 | |
|   UINT32  Index;
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done
 | |
|   //
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     Cptr = Line;
 | |
|     Cptr += SkipWhiteSpace (Line);
 | |
|     //
 | |
|     // Look for xxxGUIDyyy equ 01h, 02h, 03h, ...
 | |
|     //
 | |
|     Len = ValidSymbolName (Cptr);
 | |
|     if (Len) {
 | |
|       //
 | |
|       // Terminate the line after the symbol name, then look for "guid" in
 | |
|       // the name.
 | |
|       //
 | |
|       CSavePtr  = Cptr + Len;
 | |
|       CSave     = *CSavePtr;
 | |
|       *CSavePtr = 0;
 | |
|       while (*Cptr) {
 | |
|         if (strnicmp (Cptr, "guid", 4) == 0) {
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Cptr++;
 | |
|       }
 | |
|       //
 | |
|       // If we found the string "guid", continue
 | |
|       //
 | |
|       if (*Cptr) {
 | |
|         //
 | |
|         // Restore the character on the line where we null-terminated the symbol
 | |
|         //
 | |
|         *CSavePtr = CSave;
 | |
|         Cptr      = CSavePtr;
 | |
|         Len       = SkipWhiteSpace (Cptr);
 | |
|         //
 | |
|         // Had to be some white space
 | |
|         //
 | |
|         if (Len) {
 | |
|           Cptr += Len;
 | |
|           //
 | |
|           // now look for "equ"
 | |
|           //
 | |
|           if (strnicmp (Cptr, "equ", 3) == 0) {
 | |
|             Cptr += 3;
 | |
|             Cptr += SkipWhiteSpace (Cptr);
 | |
|             //
 | |
|             // Now scan all the data
 | |
|             //
 | |
|             for (Index = 0; Index < 16; Index++) {
 | |
|               if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) {
 | |
|                 break;
 | |
|               }
 | |
|               //
 | |
|               // Skip to next
 | |
|               //
 | |
|               while (isxdigit (*Cptr)) {
 | |
|                 Cptr++;
 | |
|               }
 | |
| 
 | |
|               if ((*Cptr != 'h') && (*Cptr != 'H')) {
 | |
|                 break;
 | |
|               } else {
 | |
|                 Cptr++;
 | |
|                 while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) {
 | |
|                   Cptr++;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|             //
 | |
|             // Now see which form we had
 | |
|             //
 | |
|             if (Index == 16) {
 | |
|               AddGuid16 (FileName, GuidData);
 | |
|             } else if (Index == 11) {
 | |
|               AddGuid11 (FileName, GuidData, NULL);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list
 | |
| // of guids.
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| AddGuid16 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD *NewRec;
 | |
|   int         Index;
 | |
| 
 | |
|   //
 | |
|   // Sanity check the data
 | |
|   //
 | |
|   if (!CheckGuidData (Data, 16)) {
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Allocate memory for a new guid structure
 | |
|   //
 | |
|   NewRec = malloc (sizeof (GUID_RECORD));
 | |
|   if (NewRec == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
 | |
|   NewRec->FileName = malloc (strlen (FileName) + 1);
 | |
|   if (NewRec->FileName == NULL) {
 | |
|     free (NewRec);
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   strcpy (NewRec->FileName, FileName);
 | |
|   NewRec->Guid.Data1  = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24));
 | |
|   NewRec->Guid.Data2  = (UINT16) (Data[4] | (Data[5] << 8));
 | |
|   NewRec->Guid.Data3  = (UINT16) (Data[6] | (Data[7] << 8));
 | |
|   for (Index = 0; Index < 8; Index++) {
 | |
|     NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8];
 | |
|   }
 | |
|   //
 | |
|   // Add it to the list
 | |
|   //
 | |
|   NewRec->Next  = gGuidList;
 | |
|   gGuidList     = NewRec;
 | |
| 
 | |
|   //
 | |
|   // Report it
 | |
|   // ReportGuid (FileName, NewRec);
 | |
|   //
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Add a GUID defined as GuidLow: 0x1122334455667788
 | |
| //                       GuidHi:  0x99AABBCCDDEEFF00
 | |
| //
 | |
| // These are equivalent:
 | |
| // { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }
 | |
| //    and:
 | |
| // Low: 00FFEEDDCCBBAA99
 | |
| // Hi:  7788556611223344
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| AddGuid64x2 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    DataHH, // Upper 32-bits of upper 64 bits of guid
 | |
|   UINT32    DataHL, // Lower 32-bits of upper 64 bits
 | |
|   UINT32    DataLH,
 | |
|   UINT32    DataLL
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD *NewRec;
 | |
|   int         Index;
 | |
| 
 | |
|   //
 | |
|   // Allocate memory for a new guid structure
 | |
|   //
 | |
|   NewRec = malloc (sizeof (GUID_RECORD));
 | |
|   if (NewRec == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
 | |
|   NewRec->FileName = malloc (strlen (FileName) + 1);
 | |
|   if (NewRec->FileName == NULL) {
 | |
|     free (NewRec);
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   strcpy (NewRec->FileName, FileName);
 | |
|   NewRec->Guid.Data1  = DataHL;
 | |
|   NewRec->Guid.Data2  = (UINT16) DataHH;
 | |
|   NewRec->Guid.Data3  = (UINT16) (DataHH >> 16);
 | |
|   for (Index = 0; Index < 4; Index++) {
 | |
|     NewRec->Guid.Data4[Index] = (UINT8) DataLL;
 | |
|     DataLL >>= 8;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 4; Index++) {
 | |
|     NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH;
 | |
|     DataLH >>= 8;
 | |
|   }
 | |
|   //
 | |
|   // Add it to the list
 | |
|   //
 | |
|   NewRec->Next  = gGuidList;
 | |
|   gGuidList     = NewRec;
 | |
| 
 | |
|   //
 | |
|   // Report it
 | |
|   // ReportGuid (FileName, NewRec);
 | |
|   //
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Process INF files. Look for:
 | |
| // FILE_GUID            = 240612B6-A063-11d4-9A3A-0090273FC14D
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessINFFileGuids (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN * 2];
 | |
|   INT8    *Cptr;
 | |
|   INT8    *Cptr2;
 | |
|   UINT32  GuidScan[11];
 | |
|   UINT64  Guid64;
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done
 | |
|   //
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     Cptr = Line;
 | |
|     Cptr += SkipWhiteSpace (Line);
 | |
|     if (strncmp (Cptr, "FILE_GUID", 9) == 0) {
 | |
|       Cptr += 9;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       if (*Cptr == '=') {
 | |
|         Cptr++;
 | |
|         Cptr += SkipWhiteSpace (Cptr + 1);
 | |
|         //
 | |
|         // Blank out dashes on the line.
 | |
|         //
 | |
|         for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
 | |
|           if (*Cptr2 == '-') {
 | |
|             *Cptr2 = ' ';
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (sscanf (
 | |
|               Cptr,
 | |
|               "%X %X %X %X %I64X",
 | |
|               &GuidScan[0],
 | |
|               &GuidScan[1],
 | |
|               &GuidScan[2],
 | |
|               &GuidScan[3],
 | |
|               &Guid64
 | |
|               ) == 5) {
 | |
|           AddPkgGuid (FileName, GuidScan, &Guid64);
 | |
|         } else {
 | |
|           DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Parse ('g','m','a','p','a','b','c','d')
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| AddSignature (
 | |
|   INT8      *FileName,
 | |
|   INT8      *StrDef,
 | |
|   UINT32    SigSize
 | |
|   )
 | |
| {
 | |
|   SIGNATURE_RECORD  *NewRec;
 | |
|   INT8              *Cptr;
 | |
|   UINT32            Index;
 | |
|   BOOLEAN           Fail;
 | |
| 
 | |
|   //
 | |
|   // Allocate memory for the new record
 | |
|   //
 | |
|   Fail    = FALSE;
 | |
|   NewRec  = malloc (sizeof (SIGNATURE_RECORD));
 | |
|   if (NewRec == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Allocate memory to save the file name
 | |
|   //
 | |
|   NewRec->FileName = malloc (strlen (FileName) + 1);
 | |
|   if (NewRec->FileName == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     free (NewRec);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Fill in the fields
 | |
|   //
 | |
|   strcpy (NewRec->FileName, FileName);
 | |
|   NewRec->Signature.DataLen = (UINT8) SigSize;
 | |
|   //
 | |
|   // Skip to open parenthesis
 | |
|   //
 | |
|   Cptr = StrDef;
 | |
|   Cptr += SkipWhiteSpace (Cptr);
 | |
|   if (*Cptr != '(') {
 | |
|     Fail = TRUE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Cptr++;
 | |
|   //
 | |
|   // Skip to first ' and start processing
 | |
|   //
 | |
|   while (*Cptr && (*Cptr != '\'')) {
 | |
|     Cptr++;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < SigSize; Index++) {
 | |
|     if (*Cptr == '\'') {
 | |
|       Cptr++;
 | |
|       NewRec->Signature.Data[Index] = (INT8) *Cptr;
 | |
|       //
 | |
|       // Skip to closing quote
 | |
|       //
 | |
|       Cptr++;
 | |
|       if (*Cptr != '\'') {
 | |
|         Fail = TRUE;
 | |
|         break;
 | |
|       }
 | |
|       //
 | |
|       // Skip over closing quote, go to next one
 | |
|       //
 | |
|       Cptr++;
 | |
|       while (*Cptr && (*Cptr != '\'')) {
 | |
|         Cptr++;
 | |
|       }
 | |
|     } else {
 | |
|       Fail = TRUE;
 | |
|       DebugMsg (NULL, 0, 0, StrDef, "failed to parse signature");
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (Fail) {
 | |
|     free (NewRec->FileName);
 | |
|     free (NewRec);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   NewRec->Next    = gSignatureList;
 | |
|   gSignatureList  = NewRec;
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Look for:
 | |
| // #define POOL_HEAD_SIGNATURE         EFI_SIGNATURE_16('p','h')
 | |
| // #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_32('g','m','a','p')
 | |
| // #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_64('g','m','a','p','a','b','c','d')
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessCFileSigs (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN * 2];
 | |
|   INT8    *Cptr;
 | |
|   UINT32  Len;
 | |
|   UINT32  LineLen;
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done
 | |
|   //
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     Cptr = Line;
 | |
|     Cptr += SkipWhiteSpace (Line);
 | |
|     //
 | |
|     // look for #define xxxGUIDxxx value
 | |
|     //
 | |
|     if (*Cptr == '#') {
 | |
|       Cptr++;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       //
 | |
|       // Look for "define"
 | |
|       //
 | |
|       if (!strncmp (Cptr, "define", 6)) {
 | |
|         Cptr += 6;
 | |
|         //
 | |
|         // Better be whitespace
 | |
|         //
 | |
|         Len = SkipWhiteSpace (Cptr);
 | |
|         if (Len) {
 | |
|           Cptr += Len;
 | |
|           //
 | |
|           // See if it's a valid symbol name
 | |
|           //
 | |
|           Len = ValidSymbolName (Cptr);
 | |
|           if (Len) {
 | |
|             //
 | |
|             // It is a valid symbol name. See if there's a line continuation,
 | |
|             // and if so, read one more line.
 | |
|             // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"
 | |
|             //
 | |
|             LineLen = strlen (Line);
 | |
|             if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
 | |
|               fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
 | |
|             } else if (Line[LineLen - 1] == '\\') {
 | |
|               fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
 | |
|             }
 | |
| 
 | |
|             Cptr += Len;
 | |
|             Cptr += SkipWhiteSpace (Cptr);
 | |
|             if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) {
 | |
|               AddSignature (FileName, Cptr + 16, 2);
 | |
|             } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) {
 | |
|               AddSignature (FileName, Cptr + 16, 4);
 | |
|             } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) {
 | |
|               AddSignature (FileName, Cptr + 16, 8);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // look for #define xxxGUIDyyy { 0x...}
 | |
| // xxx EFI_GUID  GuidName = { 0x... };
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessCFileGuids (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN * 2];
 | |
|   INT8    *Cptr;
 | |
|   INT8    CSave;
 | |
|   INT8    *CSavePtr;
 | |
|   INT8    *TempCptr;
 | |
|   INT8    *SymName;
 | |
|   UINT32  Len;
 | |
|   UINT32  LineLen;
 | |
|   UINT32  GuidScan[11];
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done
 | |
|   //
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     Cptr = Line;
 | |
|     Cptr += SkipWhiteSpace (Line);
 | |
|     //
 | |
|     // look for #define xxxGUIDxxx value
 | |
|     //
 | |
|     if (*Cptr == '#') {
 | |
|       Cptr++;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       //
 | |
|       // Look for "define"
 | |
|       //
 | |
|       if (!strncmp (Cptr, "define", 6)) {
 | |
|         Cptr += 6;
 | |
|         //
 | |
|         // Better be whitespace
 | |
|         //
 | |
|         Len = SkipWhiteSpace (Cptr);
 | |
|         if (Len) {
 | |
|           Cptr += Len;
 | |
|           //
 | |
|           // See if it's a valid symbol name
 | |
|           //
 | |
|           Len = ValidSymbolName (Cptr);
 | |
|           if (Len) {
 | |
|             //
 | |
|             // It is a valid symbol name. See if there's a line continuation,
 | |
|             // and if so, read one more line.
 | |
|             // Then truncate after the symbol name, look for the string "GUID",
 | |
|             // and continue.
 | |
|             //
 | |
|             SymName = Cptr;
 | |
|             LineLen = strlen (Line);
 | |
|             if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
 | |
|               fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
 | |
|             } else if (Line[LineLen - 1] == '\\') {
 | |
|               fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
 | |
|             }
 | |
| 
 | |
|             CSavePtr  = Cptr + Len;
 | |
|             CSave     = *CSavePtr;
 | |
|             *CSavePtr = 0;
 | |
|             while (*Cptr) {
 | |
|               if (strncmp (Cptr, "GUID", 4) == 0) {
 | |
|                 break;
 | |
|               }
 | |
| 
 | |
|               Cptr++;
 | |
|             }
 | |
|             //
 | |
|             // If we didn't run out of string, then we found the GUID string.
 | |
|             // Now look for { 0x....... }
 | |
|             //
 | |
|             if (*Cptr) {
 | |
|               Cptr      = CSavePtr;
 | |
|               *CSavePtr = CSave;
 | |
|               Cptr += SkipWhiteSpace (Cptr);
 | |
|               if (*Cptr == '{') {
 | |
|                 *Cptr = 0;
 | |
|                 Cptr++;
 | |
|                 //
 | |
|                 // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
 | |
|                 // If you have one suffixed with "L", then it doesn't work. So hack off 'L' characters
 | |
|                 // in the string.
 | |
|                 //
 | |
|                 for (TempCptr = Cptr; *TempCptr; TempCptr++) {
 | |
|                   if (*TempCptr == 'L') {
 | |
|                     if (*(TempCptr + 1) == ',') {
 | |
|                       *TempCptr       = ',';
 | |
|                       *(TempCptr + 1) = ' ';
 | |
|                     }
 | |
|                   }
 | |
|                 }
 | |
| 
 | |
|                 if (sscanf (
 | |
|                       Cptr,
 | |
|                       "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",
 | |
|                       &GuidScan[0],
 | |
|                       &GuidScan[1],
 | |
|                       &GuidScan[2],
 | |
|                       &GuidScan[3],
 | |
|                       &GuidScan[4],
 | |
|                       &GuidScan[5],
 | |
|                       &GuidScan[6],
 | |
|                       &GuidScan[7],
 | |
|                       &GuidScan[8],
 | |
|                       &GuidScan[9],
 | |
|                       &GuidScan[10]
 | |
|                       ) == 11) {
 | |
|                   AddGuid11 (FileName, GuidScan, SymName);
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       //
 | |
|       // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };
 | |
|       //
 | |
|     } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {
 | |
|       //
 | |
|       // Read the next line if line continuation
 | |
|       //
 | |
|       LineLen = strlen (Line);
 | |
|       if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
 | |
|         fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
 | |
|       } else if (Line[LineLen - 1] == '\\') {
 | |
|         fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
 | |
|       }
 | |
| 
 | |
|       Cptr = CSavePtr + 8;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       //
 | |
|       // Should be variable name next
 | |
|       //
 | |
|       Len     = ValidSymbolName (Cptr);
 | |
|       SymName = Cptr;
 | |
|       Cptr += Len;
 | |
|       Cptr += SkipWhiteSpace (Cptr);
 | |
|       if (*Cptr == '=') {
 | |
|         Cptr++;
 | |
|         Cptr += SkipWhiteSpace (Cptr);
 | |
|         //
 | |
|         // Should be open-brace next to define guid
 | |
|         //
 | |
|         if (*Cptr == '{') {
 | |
|           Cptr++;
 | |
|           //
 | |
|           // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
 | |
|           //
 | |
|           if (sscanf (
 | |
|                 Cptr,
 | |
|                 "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",
 | |
|                 &GuidScan[0],
 | |
|                 &GuidScan[1],
 | |
|                 &GuidScan[2],
 | |
|                 &GuidScan[3],
 | |
|                 &GuidScan[4],
 | |
|                 &GuidScan[5],
 | |
|                 &GuidScan[6],
 | |
|                 &GuidScan[7],
 | |
|                 &GuidScan[8],
 | |
|                 &GuidScan[9],
 | |
|                 &GuidScan[10]
 | |
|                 ) == 11) {
 | |
|             AddGuid11 (FileName, GuidScan, Cptr);
 | |
|             //
 | |
|             // printf ("Found guid: %s", Cptr);
 | |
|             //
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Process Intel Itanium(TM) GUID definitions. Look for:
 | |
| // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
 | |
| // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
 | |
| // in either order.
 | |
| // This function assumes no blank lines between definitions.
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| ProcessIA64FileGuids (
 | |
|   INT8    *FileName
 | |
|   )
 | |
| {
 | |
|   FILE    *Fptr;
 | |
|   INT8    Line[MAX_LINE_LEN];
 | |
|   UINT32  Guid1H;
 | |
|   UINT32  Guid1L;
 | |
|   UINT32  Guid2H;
 | |
|   UINT32  Guid2L;
 | |
|   INT8    SymName1[MAX_LINE_LEN];
 | |
|   INT8    SymName2[MAX_LINE_LEN];
 | |
|   BOOLEAN Done;
 | |
|   BOOLEAN LowFirst;
 | |
|   BOOLEAN FoundLow;
 | |
| 
 | |
|   if ((Fptr = fopen (FileName, "r")) == NULL) {
 | |
|     Error (NULL, 0, 0, FileName, "could not open input file for reading");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   Done = FALSE;
 | |
|   if (fgets (Line, sizeof (Line), Fptr) == NULL) {
 | |
|     Done = 1;
 | |
|   }
 | |
|   //
 | |
|   // Read lines from the file until done. Since the guid definition takes
 | |
|   // two lines, we read lines in different places to recover gracefully
 | |
|   // from mismatches. For example, if you thought you found the first half,
 | |
|   // but the next line had a symbol mismatch, then you have to process the
 | |
|   // line again in case it's the start of a new definition.
 | |
|   //
 | |
|   while (!Done) {
 | |
|     //
 | |
|     // Check current line for GUID definition. Assume low define first.
 | |
|     //
 | |
|     if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) {
 | |
|       //
 | |
|       // Might have to swap guids later. Save off if we found the LOW first
 | |
|       //
 | |
|       if (FoundLow) {
 | |
|         LowFirst = TRUE;
 | |
|       } else {
 | |
|         LowFirst = FALSE;
 | |
|       }
 | |
|       //
 | |
|       // Read the next line and try for the rest of the guid definition
 | |
|       //
 | |
|       if (fgets (Line, sizeof (Line), Fptr) == NULL) {
 | |
|         Done = 1;
 | |
|       } else {
 | |
|         if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) {
 | |
|           //
 | |
|           // Found another. If the symbol names match, then save it off.
 | |
|           //
 | |
|           if (strcmp (SymName1, SymName2) == 0) {
 | |
|             //
 | |
|             // Yea, found one. Save it off.
 | |
|             //
 | |
|             if (LowFirst) {
 | |
|               AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L);
 | |
|             } else {
 | |
|               AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L);
 | |
|             }
 | |
|             //
 | |
|             // Read the next line for processing
 | |
|             //
 | |
|             if (fgets (Line, sizeof (Line), Fptr) == NULL) {
 | |
|               Done = 1;
 | |
|             }
 | |
|           } else {
 | |
|             //
 | |
|             // Don't get another line so that we reprocess this line in case it
 | |
|             // contains the start of a new definition.
 | |
|             // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n",
 | |
|             //    FileName, SymName1, SymName2);
 | |
|             //
 | |
|           }
 | |
|         } else {
 | |
|           //
 | |
|           // Second line was not a guid definition. Get the next line from the
 | |
|           // file.
 | |
|           //
 | |
|           if (fgets (Line, sizeof (Line), Fptr) == NULL) {
 | |
|             Done = 1;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Not a guid define line. Next.
 | |
|       //
 | |
|       if (fgets (Line, sizeof (Line), Fptr) == NULL) {
 | |
|         Done = 1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Given a line from an Itanium-based assembly file, check the line for a guid
 | |
| // defininition. One of either:
 | |
| // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
 | |
| // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
 | |
| // Return the defined value as two 32-bit values, and whether it's a high
 | |
| // or low guid.
 | |
| //
 | |
| static
 | |
| BOOLEAN
 | |
| IsIA64GuidLine (
 | |
|   INT8      *Line,
 | |
|   UINT32    *GuidHigh,
 | |
|   UINT32    *GuidLow,
 | |
|   BOOLEAN   *FoundLow,
 | |
|   INT8      *SymName
 | |
|   )
 | |
| {
 | |
|   INT8    *Cptr;
 | |
|   INT8    CSave;
 | |
|   INT8    *CSavePtr;
 | |
|   INT8    *SymStart;
 | |
|   UINT32  Len;
 | |
| 
 | |
|   Cptr = Line;
 | |
|   Cptr += SkipWhiteSpace (Cptr);
 | |
|   //
 | |
|   // look for #define xxxGUID[L|H] 0xHexValue
 | |
|   //
 | |
|   if (*Cptr == '#') {
 | |
|     Cptr++;
 | |
|     Cptr += SkipWhiteSpace (Cptr);
 | |
|     //
 | |
|     // Look for "define"
 | |
|     //
 | |
|     if (!strncmp (Cptr, "define", 6)) {
 | |
|       Cptr += 6;
 | |
|       //
 | |
|       // Better be whitespace
 | |
|       //
 | |
|       Len = SkipWhiteSpace (Cptr);
 | |
|       if (Len) {
 | |
|         Cptr += Len;
 | |
|         //
 | |
|         // See if it's a valid symbol name
 | |
|         //
 | |
|         Len = ValidSymbolName (Cptr);
 | |
|         if (Len) {
 | |
|           //
 | |
|           // Save the start so we can copy it to their string if later checks are ok
 | |
|           //
 | |
|           SymStart = Cptr;
 | |
|           //
 | |
|           // It is a valid symbol name, look for the string GuidL or GuidH
 | |
|           //
 | |
|           CSavePtr  = Cptr + Len;
 | |
|           CSave     = *CSavePtr;
 | |
|           *CSavePtr = 0;
 | |
|           while (*Cptr) {
 | |
|             if (strncmp (Cptr, "GuidL", 5) == 0) {
 | |
|               *FoundLow = 1;
 | |
|               break;
 | |
|             } else if (strncmp (Cptr, "GuidH", 5) == 0) {
 | |
|               *FoundLow = 0;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             Cptr++;
 | |
|           }
 | |
|           //
 | |
|           // If we didn't run out of string, then we found the GUID string.
 | |
|           // Restore the null character we inserted above and continue.
 | |
|           // Now look for  0x.......
 | |
|           //
 | |
|           if (*Cptr) {
 | |
|             //
 | |
|             // Return symbol name less the "L" or "H"
 | |
|             //
 | |
|             strcpy (SymName, SymStart);
 | |
|             SymName[strlen (SymName) - 1] = 0;
 | |
|             Cptr                          = CSavePtr;
 | |
|             *CSavePtr                     = CSave;
 | |
|             Cptr += SkipWhiteSpace (Cptr);
 | |
|             if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) {
 | |
|               //
 | |
|               // skip over "0x"
 | |
|               //
 | |
|               Cptr += 2;
 | |
|               //
 | |
|               // 0x0123456789ABCDEF -- null terminate after 8 characters,
 | |
|               // scan, replace the character and scan at that point.
 | |
|               //
 | |
|               CSave       = *(Cptr + 8);
 | |
|               *(Cptr + 8) = 0;
 | |
|               if (sscanf (Cptr, "%X", GuidHigh) == 1) {
 | |
|                 *(Cptr + 8) = CSave;
 | |
|                 if (sscanf (Cptr + 8, "%X", GuidLow) == 1) {
 | |
|                   return TRUE;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| //
 | |
| // Look at the characters in the string and determine if it's a valid
 | |
| // symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]*
 | |
| //
 | |
| static
 | |
| UINT32
 | |
| ValidSymbolName (
 | |
|   INT8    *Name
 | |
|   )
 | |
| {
 | |
|   int Len;
 | |
| 
 | |
|   Len = 0;
 | |
| 
 | |
|   //
 | |
|   // Test first character
 | |
|   //
 | |
|   if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) {
 | |
|     Name++;
 | |
|     Len = 1;
 | |
|     while (*Name) {
 | |
|       if (((*Name >= 'a') && (*Name <= 'z')) ||
 | |
|           ((*Name >= 'A') && (*Name <= 'Z')) ||
 | |
|           ((*Name >= '0') && (*Name <= '9')) ||
 | |
|           (*Name == '_')
 | |
|           ) {
 | |
|         Name++;
 | |
|         Len++;
 | |
|       } else {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| 
 | |
| static
 | |
| UINT32
 | |
| SkipWhiteSpace (
 | |
|   INT8    *Str
 | |
|   )
 | |
| {
 | |
|   UINT32  Len;
 | |
|   Len = 0;
 | |
|   while (isspace (*Str) && *Str) {
 | |
|     Len++;
 | |
|     Str++;
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| //
 | |
| // found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| AddPkgGuid (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data,
 | |
|   UINT64    *Data64
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD *NewRec;
 | |
|   int         Index;
 | |
| 
 | |
|   //
 | |
|   // Sanity check the data
 | |
|   //
 | |
|   if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) {
 | |
|     Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // More checks for Data64?
 | |
|   // Allocate memory for a new one guid structure
 | |
|   //
 | |
|   NewRec = malloc (sizeof (GUID_RECORD));
 | |
|   if (NewRec == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
 | |
|   NewRec->FileName = malloc (strlen (FileName) + 1);
 | |
|   if (NewRec->FileName == NULL) {
 | |
|     free (NewRec);
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   strcpy (NewRec->FileName, FileName);
 | |
|   NewRec->Guid.Data1    = Data[0];
 | |
|   NewRec->Guid.Data2    = (UINT16) Data[1];
 | |
|   NewRec->Guid.Data3    = (UINT16) Data[2];
 | |
|   NewRec->Guid.Data4[0] = (UINT8) Data[3];
 | |
|   NewRec->Guid.Data4[1] = (UINT8) (Data[3] >> 8);
 | |
|   for (Index = 2; Index < 8; Index++) {
 | |
|     NewRec->Guid.Data4[Index] = (UINT8) *Data64;
 | |
|     *Data64 >>= 8;
 | |
|   }
 | |
|   //
 | |
|   // Add it to the list
 | |
|   //
 | |
|   NewRec->Next  = gGuidList;
 | |
|   gGuidList     = NewRec;
 | |
| 
 | |
|   //
 | |
|   // Report it
 | |
|   // ReportGuid (FileName, NewRec);
 | |
|   //
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // Add a guid consisting of 11 fields to our list of guids
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| AddGuid11 (
 | |
|   INT8      *FileName,
 | |
|   UINT32    *Data,
 | |
|   INT8      *SymName
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD *NewRec;
 | |
|   int         Index;
 | |
| 
 | |
|   //
 | |
|   // Sanity check the data
 | |
|   //
 | |
|   if (!CheckGuidData (Data, 11)) {
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Allocate memory for a new one guid structure
 | |
|   //
 | |
|   NewRec = malloc (sizeof (GUID_RECORD));
 | |
|   if (NewRec == NULL) {
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
 | |
|   NewRec->FileName = malloc (strlen (FileName) + 1);
 | |
|   if (NewRec->FileName == NULL) {
 | |
|     free (NewRec);
 | |
|     Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   strcpy (NewRec->FileName, FileName);
 | |
|   if (SymName != NULL) {
 | |
|     NewRec->SymName = malloc (strlen (SymName) + 1);
 | |
|     if (NewRec->SymName == NULL) {
 | |
|       free (NewRec);
 | |
|       Error (NULL, 0, 0, "memory allocation failure", NULL);
 | |
|       return STATUS_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   strcpy (NewRec->SymName, SymName);
 | |
| 
 | |
|   NewRec->Guid.Data1  = Data[0];
 | |
|   NewRec->Guid.Data2  = (UINT16) Data[1];
 | |
|   NewRec->Guid.Data3  = (UINT16) Data[2];
 | |
|   for (Index = 0; Index < 8; Index++) {
 | |
|     NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index];
 | |
|   }
 | |
|   //
 | |
|   // Add it to the list
 | |
|   //
 | |
|   NewRec->Next  = gGuidList;
 | |
|   gGuidList     = NewRec;
 | |
| 
 | |
|   //
 | |
|   // Report it
 | |
|   // ReportGuid (FileName, NewRec);
 | |
|   //
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| //
 | |
| // For debug purposes, print each guid found
 | |
| //
 | |
| // static
 | |
| // VOID
 | |
| // ReportGuid (
 | |
| //  INT8        *FileName,
 | |
| // GUID_RECORD *NewGuid
 | |
| //  )
 | |
| // {
 | |
| //  //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1);
 | |
| // }
 | |
| //
 | |
| // Free up memory we allocated to keep track of guids defined.
 | |
| //
 | |
| static
 | |
| VOID
 | |
| FreeGuids (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD *NextRec;
 | |
|   while (gGuidList != NULL) {
 | |
|     NextRec = gGuidList->Next;
 | |
|     if (gGuidList->FileName != NULL) {
 | |
|       free (gGuidList->FileName);
 | |
|     }
 | |
| 
 | |
|     if (gGuidList->SymName != NULL) {
 | |
|       free (gGuidList->SymName);
 | |
|     }
 | |
| 
 | |
|     free (gGuidList);
 | |
|     gGuidList = NextRec;
 | |
|   }
 | |
| }
 | |
| 
 | |
| static
 | |
| VOID
 | |
| FreeSigs (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   SIGNATURE_RECORD  *NextRec;
 | |
|   while (gSignatureList != NULL) {
 | |
|     NextRec = gSignatureList->Next;
 | |
|     if (gSignatureList->FileName != NULL) {
 | |
|       free (gSignatureList->FileName);
 | |
|     }
 | |
| 
 | |
|     free (gSignatureList);
 | |
|     gSignatureList = NextRec;
 | |
|   }
 | |
| }
 | |
| //
 | |
| // Scan through all guids defined and compare each for duplicates.
 | |
| //
 | |
| static
 | |
| STATUS
 | |
| CheckDuplicates (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   GUID_RECORD       *CurrentFile;
 | |
| 
 | |
|   GUID_RECORD       *TempFile;
 | |
|   SIGNATURE_RECORD  *CurrentSig;
 | |
|   SIGNATURE_RECORD  *TempSig;
 | |
|   STATUS            Status;
 | |
|   int               Index;
 | |
|   int               DupCount;
 | |
|   int               Len;
 | |
|   BOOLEAN           Same;
 | |
|   UINT32            GuidSum;
 | |
|   INT8              *SymName;
 | |
| 
 | |
|   Status = STATUS_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // If we're checking guids.....
 | |
|   //
 | |
|   if (gOptions.CheckGuids) {
 | |
|     //
 | |
|     // If -p option, print all guids found
 | |
|     //
 | |
|     if (gOptions.PrintFound) {
 | |
|       CurrentFile = gGuidList;
 | |
|       while (CurrentFile != NULL) {
 | |
|         fprintf (
 | |
|           stdout,
 | |
|           "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",
 | |
|           (UINT32) CurrentFile->Guid.Data1,
 | |
|           (UINT32) CurrentFile->Guid.Data2,
 | |
|           (UINT32) CurrentFile->Guid.Data3,
 | |
|           (UINT32) CurrentFile->Guid.Data4[0],
 | |
|           (UINT32) CurrentFile->Guid.Data4[1],
 | |
|           (UINT32) CurrentFile->Guid.Data4[2],
 | |
|           (UINT32) CurrentFile->Guid.Data4[3],
 | |
|           (UINT32) CurrentFile->Guid.Data4[4],
 | |
|           (UINT32) CurrentFile->Guid.Data4[5],
 | |
|           (UINT32) CurrentFile->Guid.Data4[6],
 | |
|           (UINT32) CurrentFile->Guid.Data4[7],
 | |
|           CurrentFile->FileName
 | |
|           );
 | |
|         CurrentFile = CurrentFile->Next;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (gOptions.GuidXReference) {
 | |
|       CurrentFile = gGuidList;
 | |
|       while (CurrentFile != NULL) {
 | |
|         //
 | |
|         // If no symbol name, print "unknown"
 | |
|         //
 | |
|         SymName = CurrentFile->SymName;
 | |
|         if (SymName == NULL) {
 | |
|           SymName = "unknown";
 | |
|         }
 | |
| 
 | |
|         fprintf (
 | |
|           stdout,
 | |
|           "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n",
 | |
|           (UINT32) CurrentFile->Guid.Data1,
 | |
|           (UINT32) CurrentFile->Guid.Data2,
 | |
|           (UINT32) CurrentFile->Guid.Data3,
 | |
|           (UINT32) CurrentFile->Guid.Data4[0],
 | |
|           (UINT32) CurrentFile->Guid.Data4[1],
 | |
|           (UINT32) CurrentFile->Guid.Data4[2],
 | |
|           (UINT32) CurrentFile->Guid.Data4[3],
 | |
|           (UINT32) CurrentFile->Guid.Data4[4],
 | |
|           (UINT32) CurrentFile->Guid.Data4[5],
 | |
|           (UINT32) CurrentFile->Guid.Data4[6],
 | |
|           (UINT32) CurrentFile->Guid.Data4[7],
 | |
|           SymName
 | |
|           );
 | |
|         CurrentFile = CurrentFile->Next;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Now go through all guids and report duplicates.
 | |
|     //
 | |
|     CurrentFile = gGuidList;
 | |
|     while (CurrentFile != NULL) {
 | |
|       DupCount  = 0;
 | |
|       TempFile  = CurrentFile->Next;
 | |
|       while (TempFile) {
 | |
|         //
 | |
|         // Compare the guids
 | |
|         //
 | |
|         if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) &&
 | |
|             (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) &&
 | |
|             (CurrentFile->Guid.Data3 == TempFile->Guid.Data3)
 | |
|             ) {
 | |
|           //
 | |
|           // OR in all the guid bytes so we can ignore NULL-guid definitions.
 | |
|           //
 | |
|           GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3;
 | |
|           Same    = TRUE;
 | |
|           for (Index = 0; Index < 8; Index++) {
 | |
|             GuidSum |= CurrentFile->Guid.Data4[Index];
 | |
|             if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) {
 | |
|               Same = FALSE;
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|           //
 | |
|           // If they're the same, and the guid was non-zero, print a message.
 | |
|           //
 | |
|           if (Same && GuidSum) {
 | |
|             if (DupCount == 0) {
 | |
|               Error (NULL, 0, 0, "duplicate GUIDS found", NULL);
 | |
|               fprintf (stdout, "   FILE1: %s\n", CurrentFile->FileName);
 | |
|             }
 | |
| 
 | |
|             DupCount++;
 | |
|             fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempFile->FileName);
 | |
|             //
 | |
|             // Flag it as reported so we don't report it again if there's three or more
 | |
|             //
 | |
|             TempFile->Reported = TRUE;
 | |
|           }
 | |
|         }
 | |
|         //
 | |
|         // Next one
 | |
|         //
 | |
|         TempFile = TempFile->Next;
 | |
|       }
 | |
|       //
 | |
|       // Print the guid if we found duplicates
 | |
|       //
 | |
|       if (DupCount) {
 | |
|         fprintf (
 | |
|           stdout,
 | |
|           "   GUID:  0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
 | |
|           (UINT32) CurrentFile->Guid.Data1,
 | |
|           (UINT32) CurrentFile->Guid.Data2,
 | |
|           (UINT32) CurrentFile->Guid.Data3,
 | |
|           (UINT32) CurrentFile->Guid.Data4[0],
 | |
|           (UINT32) CurrentFile->Guid.Data4[1],
 | |
|           (UINT32) CurrentFile->Guid.Data4[2],
 | |
|           (UINT32) CurrentFile->Guid.Data4[3],
 | |
|           (UINT32) CurrentFile->Guid.Data4[4],
 | |
|           (UINT32) CurrentFile->Guid.Data4[5],
 | |
|           (UINT32) CurrentFile->Guid.Data4[6],
 | |
|           (UINT32) CurrentFile->Guid.Data4[7]
 | |
|           );
 | |
|         //
 | |
|         // return STATUS_ERROR;
 | |
|         //
 | |
|       }
 | |
|       //
 | |
|       // Find the next one that hasn't been reported
 | |
|       //
 | |
|       do {
 | |
|         CurrentFile = CurrentFile->Next;
 | |
|       } while ((CurrentFile != NULL) && (CurrentFile->Reported));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (gOptions.CheckSignatures) {
 | |
|     //
 | |
|     // Print ones found if specified
 | |
|     //
 | |
|     if (gOptions.PrintFound) {
 | |
|       CurrentSig = gSignatureList;
 | |
|       while (CurrentSig != NULL) {
 | |
|         Len = CurrentSig->Signature.DataLen;
 | |
|         for (Index = 0; Index < Len; Index++) {
 | |
|           fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
 | |
|         }
 | |
| 
 | |
|         fprintf (stdout, "  %s\n", CurrentSig->FileName);
 | |
|         CurrentSig = CurrentSig->Next;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     CurrentSig = gSignatureList;
 | |
|     while (CurrentSig != NULL) {
 | |
|       DupCount  = 0;
 | |
|       TempSig   = CurrentSig->Next;
 | |
|       Len       = CurrentSig->Signature.DataLen;
 | |
|       while (TempSig) {
 | |
|         //
 | |
|         // Check for same length, then do string compare
 | |
|         //
 | |
|         if (Len == TempSig->Signature.DataLen) {
 | |
|           if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) {
 | |
|             //
 | |
|             // Print header message if first failure for this sig
 | |
|             //
 | |
|             if (DupCount == 0) {
 | |
|               Error (NULL, 0, 0, "duplicate signatures found", NULL);
 | |
|               fprintf (stdout, "   FILE1: %s\n", CurrentSig->FileName);
 | |
|             }
 | |
| 
 | |
|             DupCount++;
 | |
|             fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempSig->FileName);
 | |
|             TempSig->Reported = TRUE;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         TempSig = TempSig->Next;
 | |
|       }
 | |
| 
 | |
|       if (DupCount) {
 | |
|         fprintf (stdout, "   SIG:   ");
 | |
|         for (Index = 0; Index < Len; Index++) {
 | |
|           fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
 | |
|         }
 | |
| 
 | |
|         fprintf (stdout, "\n");
 | |
|       }
 | |
|       //
 | |
|       // On to the next one that hasn't been reported
 | |
|       //
 | |
|       do {
 | |
|         CurrentSig = CurrentSig->Next;
 | |
|       } while ((CurrentSig != NULL) && (CurrentSig->Reported));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| static
 | |
| VOID
 | |
| FreeOptions (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Free up any memory we allocated when processing command-line options.
 | |
| 
 | |
| Arguments:
 | |
|   None.
 | |
| 
 | |
| Returns:
 | |
|   NA
 | |
| 
 | |
| Notes:
 | |
|   We don't free up the ->Str fields because we did not allocate them.
 | |
|   Instead, we just set the pointer to point to the actual parameter
 | |
|   from the command line.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   STRING_LIST *Ptr;
 | |
|   while (gOptions.ExcludeDirs != NULL) {
 | |
|     Ptr = gOptions.ExcludeDirs->Next;
 | |
|     //
 | |
|     // free (gOptions.ExcludeDirs->Str);
 | |
|     //
 | |
|     free (gOptions.ExcludeDirs);
 | |
|     gOptions.ExcludeDirs = Ptr;
 | |
|   }
 | |
| 
 | |
|   while (gOptions.ExcludeSubDirs != NULL) {
 | |
|     Ptr = gOptions.ExcludeSubDirs->Next;
 | |
|     //
 | |
|     // free (gOptions.ExcludeSubDirs->Str);
 | |
|     //
 | |
|     free (gOptions.ExcludeSubDirs);
 | |
|     gOptions.ExcludeSubDirs = Ptr;
 | |
|   }
 | |
| 
 | |
|   while (gOptions.ExcludeExtensions != NULL) {
 | |
|     Ptr = gOptions.ExcludeExtensions->Next;
 | |
|     //
 | |
|     // free (gOptions.ExcludeExtensions->Str);
 | |
|     //
 | |
|     free (gOptions.ExcludeExtensions);
 | |
|     gOptions.ExcludeExtensions = Ptr;
 | |
|   }
 | |
| 
 | |
|   while (gOptions.ExcludeFiles != NULL) {
 | |
|     Ptr = gOptions.ExcludeFiles->Next;
 | |
|     //
 | |
|     // free (gOptions.ExcludeFiles->Str);
 | |
|     //
 | |
|     free (gOptions.ExcludeFiles);
 | |
|     gOptions.ExcludeFiles = Ptr;
 | |
|   }
 | |
| }
 | |
| //
 | |
| // Given an array of 32-bit data, validate the data for the given number of
 | |
| // guid data. For example, it might have been scanned as 16 bytes of data, or
 | |
| // 11 fields of data.
 | |
| //
 | |
| static
 | |
| BOOLEAN
 | |
| CheckGuidData (
 | |
|   UINT32    *Data,
 | |
|   UINT32    DataCount
 | |
|   )
 | |
| {
 | |
|   UINT32  Index;
 | |
| 
 | |
|   if (DataCount == 16) {
 | |
|     for (Index = 0; Index < 16; Index++) {
 | |
|       if (Data[Index] &~0xFF) {
 | |
|         return FALSE;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
|   } else if (DataCount == 11) {
 | |
|     //
 | |
|     // Data[0] never out of range (32-bit)
 | |
|     //
 | |
|     if ((Data[1] | Data[2]) &~0xFFFF) {
 | |
|       //
 | |
|       // Error ("Out of range value for GUID data word(s) [1] and/or [2]");
 | |
|       //
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     for (Index = 0; Index < 8; Index++) {
 | |
|       if (Data[Index + 3] &~0xFF) {
 | |
|         //
 | |
|         // Error ("Out of range value for GUID data byte(s) [4] - [11]");
 | |
|         //
 | |
|         return FALSE;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | 
