audk/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c

2418 lines
58 KiB
C
Raw Normal View History

/*++
Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
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 1024 // we concatenate lines sometimes
// Define a structure that correlates filename extensions to an enumerated
// type.
//
#ifdef MAX_PATH
#undef MAX_PATH
#define MAX_PATH 1024
#endif
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[8];
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
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,
INT8 *SymName
);
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
);
static
VOID
ConcatenateLines (
FILE *Fptr,
INT8 *Line,
UINT32 Len
);
/**************************** 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;
}
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 = TRUE;
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;
}
//
// 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 -? print this help text",
" ",
" Example: GuidChk -g -u build -d fv -f make.inf -e .pkg",
"",
NULL
};
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
//
if (FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR) == STATUS_SUCCESS) {
Done = FALSE;
} else {
Done = TRUE;
}
//
// 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
//
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,
INT8 *SymName
)
{
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;
}
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);
}
//
// 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;
}
memset ((char *) NewRec, 0, sizeof (SIGNATURE_RECORD));
//
// 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, FileName, "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;
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 EFI_SIGNATURE_xx 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 line continuation,
// and if so, read more lines.
// Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"
//
ConcatenateLines (Fptr, Line, sizeof(Line));
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 *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)) {
DefineLine:
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 line continuation,
// and if so, read more lines.
// Then truncate after the symbol name, look for the string "GUID",
// and continue.
//
SymName = Cptr;
ConcatenateLines (Fptr, Line, sizeof(Line));
//
// Now look for { 0x....... }
//
CSavePtr = Cptr + Len;
Cptr += Len;
Cptr += SkipWhiteSpace (Cptr);
if (*Cptr == '{') {
Cptr++;
//
// Blank out 'L', 'l', '{', '}', ',' on the line.
//
for (TempCptr = Cptr; *TempCptr; TempCptr++) {
if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
(*TempCptr == '}') || (*TempCptr == ',')) {
*TempCptr = ' ';
}
}
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) {
*CSavePtr = '\0';
AddGuid11 (FileName, GuidScan, SymName);
}
}
}
}
}
//
// Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };
//
} else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {
//
// Read more lines until met ';'
//
ConcatenateLines (Fptr, Line, sizeof(Line));
while (strstr (Line, ";") == NULL) {
LineLen = strlen (Line);
Len = sizeof(Line) - LineLen;
if (Len <= 1) {
break;
}
if (Line[LineLen - 1] == '\n') {
Cptr = Line + LineLen - 1;
*Cptr = '\0';
if (fgets (Cptr, Len, Fptr) == NULL){
break;
}
ConcatenateLines (Fptr, Line, sizeof(Line));
} else {
Cptr = Line + LineLen;
*Cptr = '\0';
if (fgets (Cptr, Len, Fptr) == NULL) {
break;
}
ConcatenateLines (Fptr, Line, sizeof(Line));
}
//
// EFI_GUID may appear in comments wihout end of ';' which may cause
// ignoring of new #define, so handle it here.
//
Cptr += SkipWhiteSpace (Cptr);
if (*Cptr == '#') {
Cptr++;
Cptr += SkipWhiteSpace (Cptr);
if (!strncmp (Cptr, "define", 6)) {
goto DefineLine;
}
}
}
Cptr = CSavePtr + 8;
Cptr += SkipWhiteSpace (Cptr);
//
// Should be variable name next
//
Len = ValidSymbolName (Cptr);
SymName = Cptr;
Cptr += Len;
CSavePtr = Cptr;
Cptr += SkipWhiteSpace (Cptr);
if (*Cptr == '=') {
*CSavePtr = '\0';
Cptr++;
Cptr += SkipWhiteSpace (Cptr);
//
// Should be open-brace next to define guid
//
if (*Cptr == '{') {
Cptr++;
//
// Blank out 'L', 'l', '{', '}', ',' on the line.
//
for (TempCptr = Cptr; *TempCptr; TempCptr++) {
if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
(*TempCptr == '}') || (*TempCptr == ',')) {
*TempCptr = ' ';
}
}
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);
}
}
}
}
}
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, SymName1);
} else {
AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L, SymName1);
}
//
// 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] >> 8);
NewRec->Guid.Data4[1] = (UINT8) Data[3];
for (Index = 2; Index < 8; Index++) {
NewRec->Guid.Data4[Index] = ((UINT8*)Data64)[7-Index];
}
//
// 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 FileName
//
SymName = CurrentFile->SymName;
if (SymName == NULL) {
//
// Assume file name will not be NULL and strlen > 0
//
SymName = CurrentFile->FileName + strlen (CurrentFile->FileName) - 1;
while ((*SymName != '\\') && (SymName > CurrentFile->FileName)) SymName --;
if (*SymName == '\\') SymName ++;
}
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;
}
static
VOID
ConcatenateLines (
FILE *Fptr,
INT8 *Line,
UINT32 Len
)
{
UINT32 LineLen;
BOOLEAN NeedCheck;
NeedCheck = TRUE;
while (NeedCheck) {
LineLen = strlen (Line);
if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
Line[LineLen - 2] = '\0';
fgets (Line + LineLen - 2, Len - LineLen, Fptr);
} else if (Line[LineLen - 1] == '\\') {
Line[LineLen - 1] = '\0';
fgets (Line + LineLen - 1, Len - LineLen, Fptr);
} else {
NeedCheck = FALSE;
}
}
}