/*++ | |
Copyright (c) 2004, 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. | |
// | |
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 | |
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; | |
} | |
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; | |
} | |
// | |
// 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 | |
// | |
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; | |
} |