/** @file | |
VfrCompiler main class and main function. | |
Copyright (c) 2004 - 2016, 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. | |
**/ | |
#include "stdio.h" | |
#include "stdlib.h" | |
#include "string.h" | |
#include "VfrCompiler.h" | |
#include "CommonLib.h" | |
#include "EfiUtilityMsgs.h" | |
PACKAGE_DATA gCBuffer; | |
PACKAGE_DATA gRBuffer; | |
CVfrStringDB gCVfrStringDB; | |
VOID | |
CVfrCompiler::DebugError ( | |
IN CHAR8 *FileName, | |
IN UINT32 LineNumber, | |
IN UINT32 MessageCode, | |
IN CONST CHAR8 *Text, | |
IN CONST CHAR8 *MsgFmt, | |
... | |
) | |
{ | |
va_list List; | |
va_start (List, MsgFmt); | |
PrintMessage ((CHAR8 *) "ERROR", FileName, LineNumber, MessageCode, (CHAR8 *) Text, (CHAR8 *) MsgFmt, List); | |
va_end (List); | |
} | |
VOID | |
CVfrCompiler::SET_RUN_STATUS ( | |
IN COMPILER_RUN_STATUS Status | |
) | |
{ | |
mRunStatus = Status; | |
} | |
BOOLEAN | |
CVfrCompiler::IS_RUN_STATUS ( | |
IN COMPILER_RUN_STATUS Status | |
) | |
{ | |
return mRunStatus == Status; | |
} | |
VOID | |
CVfrCompiler::OptionInitialization ( | |
IN INT32 Argc, | |
IN CHAR8 **Argv | |
) | |
{ | |
INT32 Index; | |
EFI_STATUS Status; | |
Status = EFI_SUCCESS; | |
SetUtilityName ((CHAR8*) PROGRAM_NAME); | |
mOptions.VfrFileName = NULL; | |
mOptions.RecordListFile = NULL; | |
mOptions.CreateRecordListFile = FALSE; | |
mOptions.CreateIfrPkgFile = FALSE; | |
mOptions.PkgOutputFileName = NULL; | |
mOptions.COutputFileName = NULL; | |
mOptions.OutputDirectory = NULL; | |
mOptions.PreprocessorOutputFileName = NULL; | |
mOptions.VfrBaseFileName = NULL; | |
mOptions.IncludePaths = NULL; | |
mOptions.SkipCPreprocessor = TRUE; | |
mOptions.CPreprocessorOptions = NULL; | |
mOptions.CompatibleMode = FALSE; | |
mOptions.HasOverrideClassGuid = FALSE; | |
mOptions.WarningAsError = FALSE; | |
mOptions.AutoDefault = FALSE; | |
mOptions.CheckDefault = FALSE; | |
memset (&mOptions.OverrideClassGuid, 0, sizeof (EFI_GUID)); | |
if (Argc == 1) { | |
Usage (); | |
SET_RUN_STATUS (STATUS_DEAD); | |
return; | |
} | |
for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) { | |
if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) { | |
Usage (); | |
SET_RUN_STATUS (STATUS_DEAD); | |
return; | |
} else if (stricmp(Argv[Index], "--version") == 0) { | |
Version (); | |
SET_RUN_STATUS (STATUS_DEAD); | |
return; | |
} else if (stricmp(Argv[Index], "-l") == 0) { | |
mOptions.CreateRecordListFile = TRUE; | |
gCIfrRecordInfoDB.TurnOn (); | |
} else if (stricmp(Argv[Index], "-i") == 0) { | |
Index++; | |
if ((Index >= Argc) || (Argv[Index][0] == '-')) { | |
DebugError (NULL, 0, 1001, "Missing option", "-i missing path argument"); | |
goto Fail; | |
} | |
AppendIncludePath(Argv[Index]); | |
} else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) { | |
Index++; | |
if ((Index >= Argc) || (Argv[Index][0] == '-')) { | |
DebugError (NULL, 0, 1001, "Missing option", "-o missing output directory name"); | |
goto Fail; | |
} | |
if (strlen (Argv[Index]) > MAX_PATH - 1) { | |
DebugError (NULL, 0, 1003, "Invalid option value", "Output directory name %s is too long", Argv[Index]); | |
goto Fail; | |
} | |
mOptions.OutputDirectory = (CHAR8 *) malloc (strlen (Argv[Index]) + strlen ("\\") + 1); | |
if (mOptions.OutputDirectory == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
goto Fail; | |
} | |
strcpy (mOptions.OutputDirectory, Argv[Index]); | |
CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1]; | |
if ((lastChar != '/') && (lastChar != '\\')) { | |
if (strchr(mOptions.OutputDirectory, '/') != NULL) { | |
strcat (mOptions.OutputDirectory, "/"); | |
} else { | |
strcat (mOptions.OutputDirectory, "\\"); | |
} | |
} | |
DebugMsg (NULL, 0, 9, (CHAR8 *) "Output Directory", (CHAR8 *) "%s", mOptions.OutputDirectory); | |
} else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) { | |
mOptions.CreateIfrPkgFile = TRUE; | |
} else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) { | |
mOptions.SkipCPreprocessor = TRUE; | |
} else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) { | |
Index++; | |
if ((Index >= Argc) || (Argv[Index][0] == '-')) { | |
DebugError (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument"); | |
goto Fail; | |
} | |
AppendCPreprocessorOptions (Argv[Index]); | |
} else if (stricmp(Argv[Index], "-c") == 0 || stricmp(Argv[Index], "--compatible-framework") == 0) { | |
mOptions.CompatibleMode = TRUE; | |
} else if (stricmp(Argv[Index], "-s") == 0|| stricmp(Argv[Index], "--string-db") == 0) { | |
Index++; | |
if ((Index >= Argc) || (Argv[Index][0] == '-')) { | |
DebugError (NULL, 0, 1001, "Missing option", "-s missing input string file name"); | |
goto Fail; | |
} | |
gCVfrStringDB.SetStringFileName(Argv[Index]); | |
DebugMsg (NULL, 0, 9, (CHAR8 *) "Input string file path", (CHAR8 *) "%s", Argv[Index]); | |
} else if ((stricmp (Argv[Index], "-g") == 0) || (stricmp (Argv[Index], "--guid") == 0)) { | |
Index++; | |
Status = StringToGuid (Argv[Index], &mOptions.OverrideClassGuid); | |
if (EFI_ERROR (Status)) { | |
DebugError (NULL, 0, 1000, "Invalid format:", "%s", Argv[Index]); | |
goto Fail; | |
} | |
mOptions.HasOverrideClassGuid = TRUE; | |
} else if (stricmp(Argv[Index], "-w") == 0 || stricmp(Argv[Index], "--warning-as-error") == 0) { | |
mOptions.WarningAsError = TRUE; | |
} else if (stricmp(Argv[Index], "-a") == 0 ||stricmp(Argv[Index], "--autodefault") == 0) { | |
mOptions.AutoDefault = TRUE; | |
} else if (stricmp(Argv[Index], "-d") == 0 ||stricmp(Argv[Index], "--checkdefault") == 0) { | |
mOptions.CheckDefault = TRUE; | |
} else { | |
DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]); | |
goto Fail; | |
} | |
} | |
if (Index != Argc - 1) { | |
DebugError (NULL, 0, 1001, "Missing option", "VFR file name is not specified."); | |
goto Fail; | |
} else { | |
if (strlen (Argv[Index]) > MAX_PATH) { | |
DebugError (NULL, 0, 1003, "Invalid option value", "VFR file name %s is too long.", Argv[Index]); | |
goto Fail; | |
} | |
mOptions.VfrFileName = (CHAR8 *) malloc (strlen (Argv[Index]) + 1); | |
if (mOptions.VfrFileName == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
goto Fail; | |
} | |
strcpy (mOptions.VfrFileName, Argv[Index]); | |
if (mOptions.OutputDirectory == NULL) { | |
mOptions.OutputDirectory = (CHAR8 *) malloc (1); | |
if (mOptions.OutputDirectory == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
goto Fail; | |
} | |
mOptions.OutputDirectory[0] = '\0'; | |
} | |
} | |
if (SetBaseFileName() != 0) { | |
goto Fail; | |
} | |
if (SetPkgOutputFileName () != 0) { | |
goto Fail; | |
} | |
if (SetCOutputFileName() != 0) { | |
goto Fail; | |
} | |
if (SetPreprocessorOutputFileName () != 0) { | |
goto Fail; | |
} | |
if (SetRecordListFileName () != 0) { | |
goto Fail; | |
} | |
return; | |
Fail: | |
SET_RUN_STATUS (STATUS_DEAD); | |
mOptions.CreateRecordListFile = FALSE; | |
mOptions.CreateIfrPkgFile = FALSE; | |
if (mOptions.VfrFileName != NULL) { | |
free (mOptions.VfrFileName); | |
mOptions.VfrFileName = NULL; | |
} | |
if (mOptions.VfrBaseFileName != NULL) { | |
free (mOptions.VfrBaseFileName); | |
mOptions.VfrBaseFileName = NULL; | |
} | |
if (mOptions.OutputDirectory != NULL) { | |
free (mOptions.OutputDirectory); | |
mOptions.OutputDirectory = NULL; | |
} | |
if (mOptions.PkgOutputFileName != NULL) { | |
free (mOptions.PkgOutputFileName); | |
mOptions.PkgOutputFileName = NULL; | |
} | |
if (mOptions.COutputFileName != NULL) { | |
free (mOptions.COutputFileName); | |
mOptions.COutputFileName = NULL; | |
} | |
if (mOptions.PreprocessorOutputFileName != NULL) { | |
free (mOptions.PreprocessorOutputFileName); | |
mOptions.PreprocessorOutputFileName = NULL; | |
} | |
if (mOptions.RecordListFile != NULL) { | |
free (mOptions.RecordListFile); | |
mOptions.RecordListFile = NULL; | |
} | |
if (mOptions.IncludePaths != NULL) { | |
delete mOptions.IncludePaths; | |
mOptions.IncludePaths = NULL; | |
} | |
if (mOptions.CPreprocessorOptions != NULL) { | |
delete mOptions.CPreprocessorOptions; | |
mOptions.CPreprocessorOptions = NULL; | |
} | |
} | |
VOID | |
CVfrCompiler::AppendIncludePath ( | |
IN CHAR8 *PathStr | |
) | |
{ | |
UINT32 Len = 0; | |
CHAR8 *IncludePaths = NULL; | |
Len = strlen (" -I ") + strlen (PathStr) + 1; | |
if (mOptions.IncludePaths != NULL) { | |
Len += strlen (mOptions.IncludePaths); | |
} | |
IncludePaths = new CHAR8[Len]; | |
if (IncludePaths == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
return; | |
} | |
IncludePaths[0] = '\0'; | |
if (mOptions.IncludePaths != NULL) { | |
strcat (IncludePaths, mOptions.IncludePaths); | |
} | |
strcat (IncludePaths, " -I "); | |
strcat (IncludePaths, PathStr); | |
if (mOptions.IncludePaths != NULL) { | |
delete mOptions.IncludePaths; | |
} | |
mOptions.IncludePaths = IncludePaths; | |
} | |
VOID | |
CVfrCompiler::AppendCPreprocessorOptions ( | |
IN CHAR8 *Options | |
) | |
{ | |
UINT32 Len = 0; | |
CHAR8 *Opt = NULL; | |
Len = strlen (Options) + strlen (" ") + 1; | |
if (mOptions.CPreprocessorOptions != NULL) { | |
Len += strlen (mOptions.CPreprocessorOptions); | |
} | |
Opt = new CHAR8[Len]; | |
if (Opt == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
return; | |
} | |
Opt[0] = 0; | |
if (mOptions.CPreprocessorOptions != NULL) { | |
strcat (Opt, mOptions.CPreprocessorOptions); | |
} | |
strcat (Opt, " "); | |
strcat (Opt, Options); | |
if (mOptions.CPreprocessorOptions != NULL) { | |
delete mOptions.CPreprocessorOptions; | |
} | |
mOptions.CPreprocessorOptions = Opt; | |
} | |
INT8 | |
CVfrCompiler::SetBaseFileName ( | |
VOID | |
) | |
{ | |
CHAR8 *pFileName, *pPath, *pExt; | |
if (mOptions.VfrFileName == NULL) { | |
return -1; | |
} | |
pFileName = mOptions.VfrFileName; | |
while ( | |
((pPath = strchr (pFileName, '\\')) != NULL) || | |
((pPath = strchr (pFileName, '/')) != NULL) | |
) | |
{ | |
pFileName = pPath + 1; | |
} | |
if (pFileName == NULL) { | |
return -1; | |
} | |
if ((pExt = strchr (pFileName, '.')) == NULL) { | |
return -1; | |
} | |
*pExt = '\0'; | |
if (strlen (pFileName) > MAX_PATH - 1) { | |
*pExt = '.'; | |
return -1; | |
} | |
mOptions.VfrBaseFileName = (CHAR8 *) malloc (strlen (pFileName) + 1); | |
if (mOptions.VfrBaseFileName == NULL) { | |
*pExt = '.'; | |
return -1; | |
} | |
strcpy (mOptions.VfrBaseFileName, pFileName); | |
*pExt = '.'; | |
return 0; | |
} | |
INT8 | |
CVfrCompiler::SetPkgOutputFileName ( | |
VOID | |
) | |
{ | |
INTN Length; | |
if (mOptions.VfrBaseFileName == NULL) { | |
return -1; | |
} | |
Length = strlen (mOptions.OutputDirectory) + | |
strlen (mOptions.VfrBaseFileName) + | |
strlen (VFR_PACKAGE_FILENAME_EXTENSION) + | |
1; | |
if (Length > MAX_PATH) { | |
return -1; | |
} | |
mOptions.PkgOutputFileName = (CHAR8 *) malloc (Length); | |
if (mOptions.PkgOutputFileName == NULL) { | |
return -1; | |
} | |
strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory); | |
strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName); | |
strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION); | |
return 0; | |
} | |
INT8 | |
CVfrCompiler::SetCOutputFileName ( | |
VOID | |
) | |
{ | |
INTN Length; | |
if (mOptions.VfrBaseFileName == NULL) { | |
return -1; | |
} | |
Length = strlen (mOptions.OutputDirectory) + | |
strlen (mOptions.VfrBaseFileName) + | |
strlen (".c") + | |
1; | |
if (Length > MAX_PATH) { | |
return -1; | |
} | |
mOptions.COutputFileName = (CHAR8 *) malloc (Length); | |
if (mOptions.COutputFileName == NULL) { | |
return -1; | |
} | |
strcpy (mOptions.COutputFileName, mOptions.OutputDirectory); | |
strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName); | |
strcat (mOptions.COutputFileName, ".c"); | |
return 0; | |
} | |
INT8 | |
CVfrCompiler::SetPreprocessorOutputFileName ( | |
VOID | |
) | |
{ | |
INTN Length; | |
if (mOptions.VfrBaseFileName == NULL) { | |
return -1; | |
} | |
Length = strlen (mOptions.OutputDirectory) + | |
strlen (mOptions.VfrBaseFileName) + | |
strlen (VFR_PREPROCESS_FILENAME_EXTENSION) + | |
1; | |
if (Length > MAX_PATH) { | |
return -1; | |
} | |
mOptions.PreprocessorOutputFileName = (CHAR8 *) malloc (Length); | |
if (mOptions.PreprocessorOutputFileName == NULL) { | |
return -1; | |
} | |
strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory); | |
strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName); | |
strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION); | |
return 0; | |
} | |
INT8 | |
CVfrCompiler::SetRecordListFileName ( | |
VOID | |
) | |
{ | |
INTN Length; | |
if (mOptions.VfrBaseFileName == NULL) { | |
return -1; | |
} | |
Length = strlen (mOptions.OutputDirectory) + | |
strlen (mOptions.VfrBaseFileName) + | |
strlen (VFR_RECORDLIST_FILENAME_EXTENSION) + | |
1; | |
if (Length > MAX_PATH) { | |
return -1; | |
} | |
mOptions.RecordListFile = (CHAR8 *) malloc (Length); | |
if (mOptions.RecordListFile == NULL) { | |
return -1; | |
} | |
strcpy (mOptions.RecordListFile, mOptions.OutputDirectory); | |
strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName); | |
strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION); | |
return 0; | |
} | |
CVfrCompiler::CVfrCompiler ( | |
IN INT32 Argc, | |
IN CHAR8 **Argv | |
) | |
{ | |
mPreProcessCmd = (CHAR8 *) PREPROCESSOR_COMMAND; | |
mPreProcessOpt = (CHAR8 *) PREPROCESSOR_OPTIONS; | |
SET_RUN_STATUS (STATUS_STARTED); | |
OptionInitialization(Argc, Argv); | |
if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) { | |
return; | |
} | |
SET_RUN_STATUS(STATUS_INITIALIZED); | |
} | |
CVfrCompiler::~CVfrCompiler ( | |
VOID | |
) | |
{ | |
if (mOptions.VfrFileName != NULL) { | |
free (mOptions.VfrFileName); | |
mOptions.VfrFileName = NULL; | |
} | |
if (mOptions.VfrBaseFileName != NULL) { | |
free (mOptions.VfrBaseFileName); | |
mOptions.VfrBaseFileName = NULL; | |
} | |
if (mOptions.OutputDirectory != NULL) { | |
free (mOptions.OutputDirectory); | |
mOptions.OutputDirectory = NULL; | |
} | |
if (mOptions.PkgOutputFileName != NULL) { | |
free (mOptions.PkgOutputFileName); | |
mOptions.PkgOutputFileName = NULL; | |
} | |
if (mOptions.COutputFileName != NULL) { | |
free (mOptions.COutputFileName); | |
mOptions.COutputFileName = NULL; | |
} | |
if (mOptions.PreprocessorOutputFileName != NULL) { | |
free (mOptions.PreprocessorOutputFileName); | |
mOptions.PreprocessorOutputFileName = NULL; | |
} | |
if (mOptions.RecordListFile != NULL) { | |
free (mOptions.RecordListFile); | |
mOptions.RecordListFile = NULL; | |
} | |
if (mOptions.IncludePaths != NULL) { | |
delete mOptions.IncludePaths; | |
mOptions.IncludePaths = NULL; | |
} | |
if (mOptions.CPreprocessorOptions != NULL) { | |
delete mOptions.CPreprocessorOptions; | |
mOptions.CPreprocessorOptions = NULL; | |
} | |
SET_RUN_STATUS(STATUS_DEAD); | |
} | |
VOID | |
CVfrCompiler::Usage ( | |
VOID | |
) | |
{ | |
UINT32 Index; | |
CONST CHAR8 *Help[] = { | |
" ", | |
"VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION, | |
"Copyright (c) 2004-2016 Intel Corporation. All rights reserved.", | |
" ", | |
"Usage: VfrCompile [options] VfrFile", | |
" ", | |
"Options:", | |
" -h, --help prints this help", | |
" --version prints version info", | |
" -l create an output IFR listing file", | |
" -o DIR, --output-directory DIR", | |
" deposit all output files to directory OutputDir", | |
" default is current directory", | |
" -b, --create-ifr-package", | |
" create an IFR HII pack file", | |
" -n, --no-pre-processing", | |
" do not preprocessing input file", | |
" -c, --compatible-framework", | |
" compatible framework vfr file", | |
" -s, --string-db", | |
" input uni string package file", | |
" -g, --guid", | |
" override class guid input", | |
" format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", | |
" -w --warning-as-error", | |
" treat warning as an error", | |
" -a --autodefaut generate default value for question opcode if some default is missing", | |
" -d --checkdefault check the default information in a question opcode", | |
NULL | |
}; | |
for (Index = 0; Help[Index] != NULL; Index++) { | |
fprintf (stdout, "%s\n", Help[Index]); | |
} | |
} | |
VOID | |
CVfrCompiler::Version ( | |
VOID | |
) | |
{ | |
UINT32 Index; | |
CONST CHAR8 *Help[] = { | |
"VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION, | |
NULL | |
}; | |
for (Index = 0; Help[Index] != NULL; Index++) { | |
fprintf (stdout, "%s\n", Help[Index]); | |
} | |
} | |
VOID | |
CVfrCompiler::PreProcess ( | |
VOID | |
) | |
{ | |
FILE *pVfrFile = NULL; | |
UINT32 CmdLen = 0; | |
CHAR8 *PreProcessCmd = NULL; | |
if (!IS_RUN_STATUS(STATUS_INITIALIZED)) { | |
goto Fail; | |
} | |
if (mOptions.SkipCPreprocessor == TRUE) { | |
goto Out; | |
} | |
if ((pVfrFile = fopen (LongFilePath (mOptions.VfrFileName), "r")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening the input VFR file", mOptions.VfrFileName); | |
goto Fail; | |
} | |
fclose (pVfrFile); | |
CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) + | |
strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName); | |
if (mOptions.CPreprocessorOptions != NULL) { | |
CmdLen += strlen (mOptions.CPreprocessorOptions); | |
} | |
if (mOptions.IncludePaths != NULL) { | |
CmdLen += strlen (mOptions.IncludePaths); | |
} | |
PreProcessCmd = new CHAR8[CmdLen + 10]; | |
if (PreProcessCmd == NULL) { | |
DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); | |
goto Fail; | |
} | |
strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " "); | |
strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " "); | |
if (mOptions.IncludePaths != NULL) { | |
strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " "); | |
} | |
if (mOptions.CPreprocessorOptions != NULL) { | |
strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " "); | |
} | |
strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > "); | |
strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName); | |
if (system (PreProcessCmd) != 0) { | |
DebugError (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd); | |
goto Fail; | |
} | |
delete[] PreProcessCmd; | |
Out: | |
SET_RUN_STATUS (STATUS_PREPROCESSED); | |
return; | |
Fail: | |
if (!IS_RUN_STATUS(STATUS_DEAD)) { | |
SET_RUN_STATUS (STATUS_FAILED); | |
} | |
delete[] PreProcessCmd; | |
} | |
extern UINT8 VfrParserStart (IN FILE *, IN INPUT_INFO_TO_SYNTAX *); | |
VOID | |
CVfrCompiler::Compile ( | |
VOID | |
) | |
{ | |
FILE *pInFile = NULL; | |
CHAR8 *InFileName = NULL; | |
INPUT_INFO_TO_SYNTAX InputInfo; | |
if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) { | |
goto Fail; | |
} | |
InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; | |
gCVfrErrorHandle.SetInputFile (InFileName); | |
gCVfrErrorHandle.SetWarningAsError(mOptions.WarningAsError); | |
if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening the input file", InFileName); | |
goto Fail; | |
} | |
InputInfo.CompatibleMode = mOptions.CompatibleMode; | |
if (mOptions.HasOverrideClassGuid) { | |
InputInfo.OverrideClassGuid = &mOptions.OverrideClassGuid; | |
} else { | |
InputInfo.OverrideClassGuid = NULL; | |
} | |
if (VfrParserStart (pInFile, &InputInfo) != 0) { | |
goto Fail; | |
} | |
fclose (pInFile); | |
if (gCFormPkg.HavePendingUnassigned () == TRUE) { | |
gCFormPkg.PendingAssignPrintAll (); | |
goto Fail; | |
} | |
SET_RUN_STATUS (STATUS_COMPILEED); | |
return; | |
Fail: | |
if (!IS_RUN_STATUS(STATUS_DEAD)) { | |
DebugError (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName); | |
SET_RUN_STATUS (STATUS_FAILED); | |
} | |
if (pInFile != NULL) { | |
fclose (pInFile); | |
} | |
} | |
VOID | |
CVfrCompiler::AdjustBin ( | |
VOID | |
) | |
{ | |
EFI_VFR_RETURN_CODE Status; | |
if (!IS_RUN_STATUS(STATUS_COMPILEED)) { | |
return; | |
} | |
if (gNeedAdjustOpcode) { | |
// | |
// When parsing the Vfr, has created some opcodes, now need to update the record info. | |
// | |
gCIfrRecordInfoDB.IfrUpdateRecordInfoForDynamicOpcode (FALSE); | |
} | |
// | |
// Check whether need to check default info for question or auto add default for question. | |
// | |
if (mOptions.AutoDefault || mOptions.CheckDefault) { | |
gCIfrRecordInfoDB.IfrCheckAddDefaultRecord (mOptions.AutoDefault, mOptions.CheckDefault); | |
} | |
// | |
// Check Binary Code consistent between Form and IfrRecord | |
// | |
// | |
// Get Package Data and IfrRecord Data | |
// | |
gCFormPkg.BuildPkg (gCBuffer); | |
gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); | |
// | |
// Compare Form and Record data | |
// | |
if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) { | |
UINT32 Index; | |
if (gCBuffer.Size != gRBuffer.Size) { | |
DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. FormBinary Size 0x%X is not same to RecordBuffer Size 0x%X", mOptions.VfrFileName, gCBuffer.Size, gRBuffer.Size); | |
} | |
for (Index = 0; Index < gCBuffer.Size; Index ++) { | |
if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) { | |
break; | |
} | |
} | |
if (Index != gCBuffer.Size) { | |
DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index); | |
} | |
DebugMsg (NULL, 0, 9, (CHAR8 *) "IFR Buffer", (CHAR8 *) "Form Buffer same to Record Buffer and Size is 0x%X", Index); | |
} else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) { | |
//ok | |
} else { | |
DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName); | |
} | |
// | |
// For UEFI mode, not do OpCode Adjust | |
// | |
if (mOptions.CompatibleMode) { | |
// | |
// Adjust Opcode to be compatible with framework vfr | |
// | |
Status = gCIfrRecordInfoDB.IfrRecordAdjust (); | |
if (Status != VFR_RETURN_SUCCESS) { | |
// | |
// Record List Adjust Failed | |
// | |
SET_RUN_STATUS (STATUS_FAILED); | |
return; | |
} | |
// | |
// Re get the IfrRecord Buffer. | |
// | |
gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); | |
} | |
return; | |
} | |
VOID | |
CVfrCompiler::GenBinary ( | |
VOID | |
) | |
{ | |
FILE *pFile = NULL; | |
if (!IS_RUN_STATUS(STATUS_COMPILEED)) { | |
goto Fail; | |
} | |
if (mOptions.CreateIfrPkgFile == TRUE) { | |
if ((pFile = fopen (LongFilePath (mOptions.PkgOutputFileName), "wb")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening file", mOptions.PkgOutputFileName); | |
goto Fail; | |
} | |
if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { | |
fclose (pFile); | |
goto Fail; | |
} | |
fclose (pFile); | |
} | |
SET_RUN_STATUS (STATUS_GENBINARY); | |
return; | |
Fail: | |
if (!IS_RUN_STATUS(STATUS_DEAD)) { | |
SET_RUN_STATUS (STATUS_FAILED); | |
} | |
} | |
static const char *gSourceFileHeader[] = { | |
"//", | |
"// DO NOT EDIT -- auto-generated file", | |
"//", | |
"// This file is generated by the vfrcompiler utility", | |
"//", | |
NULL | |
}; | |
VOID | |
CVfrCompiler::GenCFile ( | |
VOID | |
) | |
{ | |
FILE *pFile; | |
UINT32 Index; | |
if (!IS_RUN_STATUS(STATUS_GENBINARY)) { | |
goto Fail; | |
} | |
if (!mOptions.CreateIfrPkgFile || mOptions.CompatibleMode) { | |
if ((pFile = fopen (LongFilePath (mOptions.COutputFileName), "w")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening output C file", mOptions.COutputFileName); | |
goto Fail; | |
} | |
for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) { | |
fprintf (pFile, "%s\n", gSourceFileHeader[Index]); | |
} | |
if (mOptions.CompatibleMode) { | |
gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName); | |
} | |
if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { | |
fclose (pFile); | |
goto Fail; | |
} | |
fclose (pFile); | |
} | |
SET_RUN_STATUS (STATUS_FINISHED); | |
return; | |
Fail: | |
if (!IS_RUN_STATUS(STATUS_DEAD)) { | |
SET_RUN_STATUS (STATUS_FAILED); | |
} | |
} | |
VOID | |
CVfrCompiler::GenRecordListFile ( | |
VOID | |
) | |
{ | |
CHAR8 *InFileName = NULL; | |
FILE *pInFile = NULL; | |
FILE *pOutFile = NULL; | |
CHAR8 LineBuf[MAX_VFR_LINE_LEN]; | |
UINT32 LineNo; | |
InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; | |
if (mOptions.CreateRecordListFile == TRUE) { | |
if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) { | |
return; | |
} | |
if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName); | |
return; | |
} | |
if ((pOutFile = fopen (LongFilePath (mOptions.RecordListFile), "w")) == NULL) { | |
DebugError (NULL, 0, 0001, "Error opening the record list file", mOptions.RecordListFile); | |
goto Err1; | |
} | |
fprintf (pOutFile, "//\n// VFR compiler version " VFR_COMPILER_VERSION __BUILD_VERSION "\n//\n"); | |
LineNo = 0; | |
while (!feof (pInFile)) { | |
if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) { | |
fprintf (pOutFile, "%s", LineBuf); | |
LineNo++; | |
gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo); | |
} | |
} | |
fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n"); | |
gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0); | |
gCVfrVarDataTypeDB.Dump(pOutFile); | |
fclose (pOutFile); | |
fclose (pInFile); | |
} | |
return; | |
Err1: | |
fclose (pInFile); | |
} | |
int | |
main ( | |
IN int Argc, | |
IN char **Argv | |
) | |
{ | |
COMPILER_RUN_STATUS Status; | |
SetPrintLevel(WARNING_LOG_LEVEL); | |
CVfrCompiler Compiler(Argc, Argv); | |
Compiler.PreProcess(); | |
Compiler.Compile(); | |
Compiler.AdjustBin(); | |
Compiler.GenBinary(); | |
Compiler.GenCFile(); | |
Compiler.GenRecordListFile (); | |
Status = Compiler.RunStatus (); | |
if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) { | |
return 2; | |
} | |
if (gCBuffer.Buffer != NULL) { | |
delete gCBuffer.Buffer; | |
} | |
if (gRBuffer.Buffer != NULL) { | |
delete gRBuffer.Buffer; | |
} | |
return GetUtilityStatus (); | |
} | |