summaryrefslogtreecommitdiff
path: root/Tools/Source/TianoTools/VfrCompile
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /Tools/Source/TianoTools/VfrCompile
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'Tools/Source/TianoTools/VfrCompile')
-rw-r--r--Tools/Source/TianoTools/VfrCompile/EfiVfr.h181
-rw-r--r--Tools/Source/TianoTools/VfrCompile/VfrCompile.g3527
-rw-r--r--Tools/Source/TianoTools/VfrCompile/VfrServices.cpp757
-rw-r--r--Tools/Source/TianoTools/VfrCompile/VfrServices.h227
-rw-r--r--Tools/Source/TianoTools/VfrCompile/build.gcc10
-rw-r--r--Tools/Source/TianoTools/VfrCompile/build.xml142
6 files changed, 4844 insertions, 0 deletions
diff --git a/Tools/Source/TianoTools/VfrCompile/EfiVfr.h b/Tools/Source/TianoTools/VfrCompile/EfiVfr.h
new file mode 100644
index 0000000000..f7c534d336
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/EfiVfr.h
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 2004 - 2005, 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:
+
+ EfiVfr.h
+
+Abstract:
+
+ Defines and prototypes for the EFI internal forms representation
+ setup protocol and drivers
+
+--*/
+
+#ifndef _EFI_VFR_H_
+#define _EFI_VFR_H_
+
+#include <Base.h>
+#include <UefiBaseTypes.h>
+#include "InternalFormRepresentation.h"
+#include <string.h>
+
+//
+// This number should be incremented with each change to the VFR compiler.
+// We write the version to the output list file for debug purposes.
+//
+#define VFR_COMPILER_VERSION "1.88"
+
+//
+// Maximum file path for filenames
+//
+#ifndef MAX_PATH
+#define MAX_PATH 255
+#endif
+#define MAX_QUEUE_COUNT 255
+#define MAX_LINE_LEN 1024
+#define PROGRAM_NAME "VfrCompile"
+
+//
+// We parse C-style structure definitions which can then be referenced
+// in VFR statements.
+// We need to define an internal structure that can be used to
+// track the fields in a structure definition, and another structure
+// to keep track of the structure name and subfields.
+//
+typedef struct _STRUCT_FIELD_DEFINITION {
+ struct _STRUCT_FIELD_DEFINITION *Next;
+ int DataSize;
+ int Offset; // from the start of the structure
+ int ArrayLength;
+ char IsArray;
+ char *Name;
+} STRUCT_FIELD_DEFINITION;
+
+typedef struct _STRUCT_DEFINITION {
+ struct _STRUCT_DEFINITION *Next;
+ int Size;
+ int LineNum; // line number where the structure was defined
+ int IsNonNV; // if this is the non-NV data structure definition
+ int Referenced; // if it's referenced anywhere in the VFR
+ int VarStoreIdValid; // found a 'varstore' statement for it in the VFR
+ unsigned short VarStoreId; // key from a varstore IFR statement
+ int VarStoreLineNum; // line number where VARSTORE was defined
+ char *Name;
+ STRUCT_FIELD_DEFINITION *Field;
+ STRUCT_FIELD_DEFINITION *LastField;
+} STRUCT_DEFINITION;
+
+//
+// For the IdEqValList variable list of UINT16's, keep track of them using
+// a linked list until we know how many there are.
+// We also use a linked list of these to keep track of labels used in
+// the VFR script so we can catch duplicates.
+// We'll also use it to keep track of defined varstore id's so we can
+// detect duplicate definitions.
+//
+typedef struct _UINT16_LIST {
+ struct _UINT16_LIST *Next;
+ UINT16 Value;
+ UINT32 LineNum;
+} UINT16_LIST;
+
+typedef struct _GOTO_REFERENCE {
+ struct _GOTO_REFERENCE *Next;
+ UINT32 RefLineNum; // line number of source file where referenced
+ UINT16 Value;
+} GOTO_REFERENCE;
+
+typedef struct _FORM_ID_VALUE {
+ struct _FORM_ID_VALUE *Next;
+ UINT32 LineNum;
+ UINT16 Value;
+} FORM_ID_VALUE;
+
+//
+// We keep track in the parser of all "#line 4 "x.y"" strings so we
+// can cross-reference the line numbers in the preprocessor output .i file
+// to the original input files.
+//
+typedef struct _PARSER_LINE_DEFINITION {
+ struct _PARSER_LINE_DEFINITION *Next;
+ UINT32 HashLineNum; // from the #line stmt
+ UINT32 TokenLineNum; // line number in the .i file
+ CHAR8 *FileName; // from the #line stmt
+} PARSER_LINE_DEFINITION;
+
+extern PARSER_LINE_DEFINITION *gLineDefinition;
+extern PARSER_LINE_DEFINITION *gLastLineDefinition;
+
+extern
+char *
+ConvertLineNumber (
+ UINT32 *LineNum
+ )
+/*++
+
+Routine Description:
+ Given the line number in the preprocessor-output file, use the line number
+ information we've saved to determine the source file name and line number
+ where the code originally came from. This is required for error reporting.
+
+Arguments:
+ LineNum - the line number in the preprocessor-output file.
+
+Returns:
+ Returns a pointer to the source file name. Also returns the line number
+ in the provided LineNum argument
+
+--*/
+;
+
+typedef struct _IFR_BYTE {
+ struct _IFR_BYTE *Next;
+ UINT32 LineNum;
+ UINT8 OpcodeByte;
+ UINT8 KeyByte;
+} IFR_BYTE;
+
+typedef struct {
+ CHAR8 VfrFileName[MAX_PATH];
+ CHAR8 VfrListFileName[MAX_PATH];
+ INT8 CreateListFile;
+ INT8 CreateIfrBinFile;
+ CHAR8 IfrOutputFileName[MAX_PATH];
+ CHAR8 OutputDirectory[MAX_PATH];
+ CHAR8 PreprocessorOutputFileName[MAX_PATH];
+ CHAR8 VfrBaseFileName[MAX_PATH]; // name of input VFR file with no path or extension
+ CHAR8 *IncludePaths;
+ CHAR8 *CPreprocessorOptions;
+} OPTIONS;
+
+extern OPTIONS gOptions;
+
+VOID
+WriteStandardFileHeader (
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+ This function is invoked to emit a standard header to an
+ output text file.
+
+Arguments:
+ OutFptr - file to write the header to
+
+Returns:
+ None
+
+--*/
+;
+
+#endif // #ifndef _EFI_VFR_H_
diff --git a/Tools/Source/TianoTools/VfrCompile/VfrCompile.g b/Tools/Source/TianoTools/VfrCompile/VfrCompile.g
new file mode 100644
index 0000000000..3646c5d1cd
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/VfrCompile.g
@@ -0,0 +1,3527 @@
+/*++
+
+Copyright (c) 2004 - 2005, 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:
+
+ VfrCompile.g
+
+Abstract:
+
+ PCCTS parser and lexer definitions for the EFI VFR forms compiler
+
+--*/
+
+#header<<
+
+#include <Base.h>
+#include <UefiBaseTypes.h>
+#include <CommonLib.h>
+#include <MultiPhase.h>
+#include "EfiUtilityMsgs.h"
+#include "EfiVfr.h"
+#include "VfrServices.h"
+#include <UgaDraw.h>
+#include <Hii.h>
+
+#include <ctype.h>
+#ifndef __GNUC__
+#include <direct.h>
+#include <process.h> // for spawn functions
+#else
+#include <unistd.h>
+#endif
+
+>>
+
+<<
+
+//
+// Base info for DLG-generated scanner
+//
+#include "DLexerBase.h"
+
+//
+// Include the scanner file generated by DLG
+//
+#include "DLGLexer.h"
+
+class DLGLexerVfr : public DLGLexer
+{
+public:
+ DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};
+ INT32 errstd (char *Text)
+ {
+ printf ("unrecognized input '%s'\n", Text);
+ }
+};
+
+//
+// Base token definitions for ANTLR
+//
+#include "AToken.h"
+
+//
+// This is how we invoke the C preprocessor on the VFR source file
+// to resolve #defines, #includes, etc. To make C source files
+// shareable between VFR and drivers, define VFRCOMPILE so that
+// #ifdefs can be used in shared .h files.
+//
+#ifdef __GNUC__
+#define PREPROCESSOR_COMMAND "gcc "
+#define PREPROCESSOR_OPTIONS "-x c -E -P -DVFRCOMPILE "
+#define FILE_SEP_CHAR '/'
+#define FILE_SEP_STRING "/"
+#else
+#define PREPROCESSOR_COMMAND "cl.exe "
+#define PREPROCESSOR_OPTIONS "/nologo /P /TC /DVFRCOMPILE "
+#define FILE_SEP_CHAR '/'
+#define FILE_SEP_STRING "/"
+#endif
+
+typedef ANTLRCommonToken ANTLRToken;
+
+//
+// Specify the filename extensions for the files we generate.
+//
+#define VFR_BINARY_FILENAME_EXTENSION ".c"
+#define VFR_LIST_FILENAME_EXTENSION ".lst"
+
+static
+VOID
+Usage ();
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+VOID
+Cleanup ();
+
+//
+// Globals
+//
+OPTIONS gOptions;
+
+int
+main (
+ int argc,
+ char **argv
+ )
+/*++
+
+Routine Description:
+ Application entry point function. Parse command-line arguments,
+ invoke the parser, clean up, and return.
+
+Arguments:
+ argc - standard argc passed to main() per C conventions
+ argv - standard argv passed to main() per C conventions
+
+Returns:
+ STATUS_SUCCESS - program executed with no errors or warnings
+ STATUS_WARNING - program executed with warnings
+ STATUS_ERROR - non-recoverable errors encountered while processing
+
+--*/
+{
+ FILE *VfrFptr;
+ char *Cmd;
+ char *Cptr;
+ int Len;
+ STATUS Status;
+
+ //
+ // Set our program name for the error printing routines.
+ // Then set printing limits.
+ //
+ SetUtilityName (PROGRAM_NAME);
+ SetPrintLimits (20, 20, 30);
+ //
+ // Process the command-line arguments
+ //
+ if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {
+ Usage ();
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ VfrFptr = NULL;
+ //
+ // Verify the VFR script file exists
+ //
+ if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ //
+ // Now close the file and make a system call to run the preprocessor
+ // on it.
+ //
+ fclose (VfrFptr);
+ Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ Len += strlen (gOptions.CPreprocessorOptions) + 1;
+ }
+ if (gOptions.IncludePaths != NULL) {
+ Len += strlen (gOptions.IncludePaths) + 1;
+ }
+ Cmd = (char *)malloc (Len);
+ if (Cmd == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ strcpy (Cmd, PREPROCESSOR_OPTIONS);
+ if (gOptions.IncludePaths != NULL) {
+ strcat (Cmd, gOptions.IncludePaths);
+ strcat (Cmd, " ");
+ }
+ if (gOptions.CPreprocessorOptions != NULL) {
+ strcat (Cmd, gOptions.CPreprocessorOptions);
+ strcat (Cmd, " ");
+ }
+ strcat (Cmd, gOptions.VfrFileName);
+#ifndef __GNUC__
+ Status = _spawnlp (_P_WAIT, PREPROCESSOR_COMMAND, Cmd, NULL);
+#else
+ {
+ char CommandLine[1000];
+ char *p;
+
+ //
+ // Lean the slashes forward.
+ //
+ for (p = gOptions.PreprocessorOutputFileName; *p; p++) {
+ if (*p=='\\') {
+ *p=FILE_SEP_CHAR;
+ }
+ }
+
+ //
+ // Lean the slashes forward.
+ //
+ for (p = Cmd; *p; p++) {
+ if (*p=='\\') {
+ *p=FILE_SEP_CHAR;
+ }
+ }
+
+ sprintf(CommandLine, "%s %s > %s", PREPROCESSOR_COMMAND, Cmd, gOptions.PreprocessorOutputFileName);
+ Status = system (CommandLine);
+ }
+#endif
+ if (Status != 0) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");
+ printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ free (Cmd);
+ //
+ // Open the preprocessor output file
+ //
+ if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file",
+ gOptions.PreprocessorOutputFileName);
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ //
+ // Define input VFR file
+ //
+ DLGFileInput InputFile (VfrFptr);
+ //
+ // Define an instance of the scanner
+ //
+ DLGLexerVfr Scanner (&InputFile);
+ //
+ // Define token buffer between scanner and parser
+ //
+ ANTLRTokenBuffer Pipe (&Scanner);
+ //
+ // Create a token to use as a model
+ //
+ ANTLRToken Tok;
+ //
+ // Tell the scanner what type the token is
+ //
+ Scanner.setToken (&Tok);
+ //
+ // Create an instance of our parser
+ //
+ EfiVfrParser Parser (&Pipe);
+ //
+ // Initialize the parser
+ //
+ Parser.init ();
+ Status = GetUtilityStatus ();
+ if (Status != STATUS_SUCCESS) {
+ Cleanup();
+ return Status;
+ }
+ //
+ // Start the first rule
+ //
+ Parser.program ();
+ //
+ // Close the input script file
+ //
+ fclose (VfrFptr);
+ Parser.WriteIfrBytes ();
+ //
+ // Call cleanup, which does some extra checking of the script
+ //
+ Parser.Cleanup ();
+ Cleanup();
+ //
+ // If we had an error somewhere, delete our output files so that
+ // a subsequent build will rebuild them.
+ //
+ Status = GetUtilityStatus ();
+ if (Status == STATUS_ERROR) {
+ remove (gOptions.IfrOutputFileName);
+ }
+ return Status;
+}
+static
+VOID
+Cleanup ()
+/*++
+
+Routine Description:
+ Free up memory allocated during parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // Free up our string we allocated to track the include paths
+ //
+ if (gOptions.IncludePaths != NULL) {
+ free (gOptions.IncludePaths);
+ gOptions.IncludePaths = NULL;
+ }
+ //
+ // Free up our string we allocated to track preprocessor options
+ //
+ if (gOptions.CPreprocessorOptions != NULL) {
+ free (gOptions.CPreprocessorOptions);
+ gOptions.CPreprocessorOptions = NULL;
+ }
+}
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command-line arguments.
+
+Arguments:
+ Argc - standard argc passed to main()
+ Argv - standard argv passed to main()
+
+Returns:
+ STATUS_SUCCESS - program should continue (all args ok)
+
+--*/
+{
+ char *IncludePaths;
+ char *CPreprocessorOptions;
+ int Len;
+ char CopyStr[MAX_PATH];
+ char *Cptr;
+
+ //
+ // Put options in known state.
+ //
+ memset ((char *)&gOptions, 0, sizeof (OPTIONS));
+ //
+ // Go through all the arguments that start with '-'
+ //
+ Argc--;
+ Argv++;
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ //
+ // -? or -h help option -- return an error for printing usage
+ //
+ if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {
+ return STATUS_ERROR;
+ break;
+ //
+ // -l to create a listing output file
+ //
+ } else if (stricmp (Argv[0], "-l") == 0) {
+ gOptions.CreateListFile = 1;
+ //
+ // -I include_path option for finding include files. We'll pass this
+ // to the preprocessor. Turn them all into a single include string.
+ //
+ } else if (stricmp (Argv[0], "-i") == 0) {
+ if ((Argc < 2) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ Len = strlen (" -I ");
+ Len += strlen (Argv[0]) + 2;
+ if (gOptions.IncludePaths != NULL) {
+ Len += strlen (gOptions.IncludePaths);
+ }
+ IncludePaths = (CHAR8 *)malloc (Len);
+ if (IncludePaths == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+ IncludePaths[0] = 0;
+ if (gOptions.IncludePaths != NULL) {
+ strcpy (IncludePaths, gOptions.IncludePaths);
+ free (gOptions.IncludePaths);
+ }
+ strcat (IncludePaths, " -I ");
+ strcat (IncludePaths, Argv[0]);
+ gOptions.IncludePaths = IncludePaths;
+ //
+ // -od OutputDirectory to define a common directory for output files
+ //
+ } else if (stricmp (Argv[0], "-od") == 0) {
+ if ((Argc < 2) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ strcpy (gOptions.OutputDirectory, Argv[0]);
+ } else if (stricmp (Argv[0], "-ibin") == 0) {
+ gOptions.CreateIfrBinFile = 1;
+ } else if (stricmp (Argv[0], "-nostrings") == 0) {
+ // deprecated option
+ //
+ // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
+ // Turn them all into a single string.
+ //
+ } else if (stricmp (Argv[0], "-ppflag") == 0) {
+ if (Argc < 2) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ Len = strlen (Argv[0]) + 2;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ Len += strlen (gOptions.CPreprocessorOptions);
+ }
+ CPreprocessorOptions = (CHAR8 *)malloc (Len);
+ if (CPreprocessorOptions == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+ CPreprocessorOptions[0] = 0;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
+ free (gOptions.CPreprocessorOptions);
+ }
+ strcat (CPreprocessorOptions, " ");
+ strcat (CPreprocessorOptions, Argv[0]);
+ gOptions.CPreprocessorOptions = CPreprocessorOptions;
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ }
+ //
+ // Must specify at least the vfr file name
+ //
+ if (Argc > 1) {
+ Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
+ return STATUS_ERROR;
+ } else if (Argc < 1) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");
+ return STATUS_ERROR;
+ }
+ strcpy (gOptions.VfrFileName, Argv[0]);
+ //
+ // We run the preprocessor on the VFR file to manage #include statements.
+ // Unfortunately the preprocessor does not allow you to specify the
+ // output name or path of the resultant .i file, so we have to do
+ // some work. Here we'll extract the basename of the VFR file, then
+ // append .i on the end.
+ //
+ strcpy (CopyStr, gOptions.VfrFileName);
+ Cptr = CopyStr + strlen (CopyStr) - 1;
+ for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':') && (*Cptr != '/'); Cptr--);
+ if (Cptr == CopyStr) {
+ strcpy (gOptions.PreprocessorOutputFileName, Cptr);
+ strcpy (gOptions.VfrBaseFileName, Cptr);
+ } else {
+ strcpy (gOptions.PreprocessorOutputFileName, Cptr+1);
+ strcpy (gOptions.VfrBaseFileName, Cptr+1);
+ }
+ for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++);
+ strcpy (Cptr, ".i");
+ //
+ // Terminate the vfr file basename at the extension
+ //
+ for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
+ }
+ *Cptr = 0;
+ //
+ // If they defined an output directory, prepend all output files
+ // with the working directory. Output files of interest:
+ // VfrListFileName -- list file
+ // IfrOutputFileName -- IFR bytes
+ // StringOutputFileName -- string bytes
+ // StringListFileName -- not used
+ // StringDefineFileName -- #defines of string identifiers
+ //
+ // We have two cases:
+ // 1. Output directory (-od) not specified, in which case output files
+ // go to the current working directory.
+ // 2. Output directory specified, in which case the output files
+ // go directly to the specified directory.
+ //
+ if (gOptions.OutputDirectory[0] == 0) {
+ CopyStr[0] = 0;
+#ifndef __GNUC__
+ _getcwd (CopyStr, sizeof (CopyStr));
+#else
+ getcwd (CopyStr, sizeof (CopyStr));
+#endif
+ strcpy (gOptions.OutputDirectory, CopyStr);
+ }
+ //
+ // Make sure output directory has a trailing backslash
+ //
+ if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\' ||
+ gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '/') {
+ strcat (gOptions.OutputDirectory, FILE_SEP_STRING);
+ }
+ //
+ // Create the base output file name as: path\base, copy it to all the output
+ // filenames, and then add the appropriate extension to each.
+ //
+ strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);
+ strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);
+ strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);
+ strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);
+ strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);
+ //
+ // We set a default list file name, so if they do not
+ // want a list file, null out the name now.
+ //
+ if (gOptions.CreateListFile == 0) {
+ gOptions.VfrListFileName[0] = 0;
+ }
+ return STATUS_SUCCESS;
+}
+static
+VOID
+Usage ()
+/*++
+
+Routine Description:
+ Print utility usage instructions
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ int Index;
+ const char *Help[] = {
+ " ",
+ "VfrCompile version " VFR_COMPILER_VERSION,
+ " ",
+ " Usage: VfrCompile {options} [VfrFile]",
+ " ",
+ " where options include:",
+ " -? or -h prints this help",
+ " -l create an output IFR listing file",
+ " -i IncPath add IncPath to the search path for VFR included files",
+ " -od OutputDir deposit all output files to directory OutputDir (default=cwd)",
+ " -ibin create an IFR HII pack file",
+ " where parameters include:",
+ " VfrFile name of the input VFR script file",
+ " ",
+ NULL
+ };
+ for (Index = 0; Help[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Help[Index]);
+ }
+}
+
+>>
+
+
+#lexaction
+<<
+
+#include "EfiVfr.h"
+
+PARSER_LINE_DEFINITION *gLineDefinition = NULL;
+PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;
+
+VOID
+AddFileLine (
+ char *TokenString,
+ UINT32 TokenLine
+ )
+/*++
+
+Routine Description:
+ During the lexer phase, if we encounter a #line statement output by
+ the preprocessor, this function gets called. We'll save off the info
+ for error reporting purposes. The preprocessor line information has the
+ form:
+
+ #line 3 "FileName.c"
+
+Arguments:
+ TokenString - the parsed string as shown above
+ TokenLine - the line number in the preprocessed output file
+
+Returns:
+ NA
+
+--*/
+{
+ PARSER_LINE_DEFINITION *LineDef;
+ CHAR8 *Cptr;
+
+ //
+ // Allocate a structure in which we can keep track of this line information.
+ //
+ LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));
+ memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));
+ LineDef->TokenLineNum = TokenLine;
+ LineDef->HashLineNum = atoi (TokenString + 6);
+ //
+ // Find the quotes in the filename, then allocate space in the line
+ // def structure for a copy of the filename. Finally, copy it without
+ // quotes to the line def.
+ //
+ for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
+ if (*Cptr == '"') {
+ LineDef->FileName = (CHAR8 *)malloc (strlen (Cptr));
+ Cptr++;
+ strcpy (LineDef->FileName, Cptr);
+ for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
+ *Cptr = 0;
+ //
+ // Now add this new one to the list
+ //
+ if (gLineDefinition == NULL) {
+ gLineDefinition = LineDef;
+ } else {
+ gLastLineDefinition->Next = LineDef;
+ }
+ gLastLineDefinition = LineDef;
+ } else {
+ Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
+ free (LineDef);
+ return;
+ }
+}
+char *
+ConvertLineNumber (
+ UINT32 *LineNum
+ )
+/*++
+
+Routine Description:
+ Given the line number in the preprocessor-output file, use the line number
+ information we've saved to determine the source file name and line number
+ where the code originally came from. This is required for error reporting.
+
+Arguments:
+ LineNum - the line number in the preprocessor-output file.
+
+Returns:
+ Returns a pointer to the source file name. Also returns the line number
+ in the provided LineNum argument
+
+--*/
+{
+ PARSER_LINE_DEFINITION *LineDef;
+ //
+ // Step through our linked list of #line information we saved off.
+ // For each one, look at its line number, and the line number of the
+ // next record, and see if the passed-in line number is in the range.
+ // If it is, then convert the line number to the appropriate line number
+ // of the original source file.
+ //
+ for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
+ //
+ // The given LineNum is the line number from the .i file.
+ // Find a line definition whose range includes this line number,
+ // convert the line number, and return the filename.
+ //
+ if (LineDef->TokenLineNum <= *LineNum) {
+ if (LineDef->Next != NULL) {
+ if (LineDef->Next->TokenLineNum > *LineNum) {
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
+ return LineDef->FileName;
+ }
+ } else {
+ //
+ // Last one in the list of line definitions, so has to be right
+ //
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
+ return LineDef->FileName;
+ }
+ }
+ }
+ return NULL;
+}
+
+>>
+
+//
+// Define a lexical class for parsing quoted strings. Basically
+// starts with a double quote, and ends with a double quote that
+// is not preceeded with a backslash.
+//
+#lexclass QUOTED_STRING
+#token TheString "~[\"]*\"" << mode (START); >>
+
+//
+// Define a lexical class for parsing "#pragma pack" statements.
+// We do this just for convenience (since we skip them here) so
+// that users can include some minimal .h files.
+//
+#lexclass PRAGMA_PACK
+#token "pack" << skip (); >>
+#token "[\ \t]" << skip (); >>
+#token "\(" << skip (); >>
+#token "[0-9]*" << skip (); >>
+#token "\)" << skip (); mode (START); >>
+
+//
+// Define a lexclass for skipping over C++ style comments
+//
+#lexclass CPP_COMMENT
+#token "~[\n]*" << skip (); >>
+#token "\n" << skip (); mode (START); newline (); >>
+
+//
+// Standard lexclass is START
+//
+#lexclass START
+
+//
+// Find start of C++ style comments
+//
+#token "//" << skip (); mode (CPP_COMMENT); >>
+
+//
+// Skip whitespace
+//
+#token "[\ \t]" << skip (); >>
+
+//
+// Skip over newlines, but count them
+//
+#token "\n" << skip (); newline (); >>
+
+//
+// Skip pragma pack statements
+//
+#token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
+
+//
+// Skip over 'extern' in any included .H file
+//
+#token "extern" << skip (); >>
+
+//
+// Tokens for the different keywords. Syntax is:
+// TokenName("ErrorMessageText") "TokenString"
+// where:
+// TokenName is the token name (must be capitalized) that is used in the rules
+// ErrorMessageText is the string the compiler emits when it detects a syntax error
+// TokenString is the actual matching string used in the user script
+//
+#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>
+#token FormSet("formset") "formset"
+#token EndFormSet("endformset") "endformset"
+#token Title("title") "title"
+#token FormId("formid") "formid"
+#token OneOf("oneof") "oneof"
+#token Prompt("prompt") "prompt"
+#token OrderedList("orderedlist") "orderedlist"
+#token EndList("endlist") "endlist"
+#token EndForm("endform") "endform"
+#token EndOneOf("endoneof") "endoneof"
+#token Form("form") "form"
+#token Subtitle("subtitle") "subtitle"
+#token Help("help") "help"
+#token VarId("varid") "varid"
+#token Text("text") "text"
+#token Option("option") "option"
+#token Value("value") "value"
+#token Flags("flags") "flags"
+#token Date("date") "date"
+#token EndDate("enddate") "enddate"
+#token Year("year") "year"
+#token Month("month") "month"
+#token Day("day") "day"
+#token Time("time") "time"
+#token EndTime("endtime") "endtime"
+#token Hour("hour") "hour"
+#token Minute("minute") "minute"
+#token Second("second") "second"
+#token AND("AND") "AND"
+#token OR("OR") "OR"
+#token GrayOutIf("grayoutif") "grayoutif"
+#token NOT("NOT") "NOT"
+#token Label("label") "label"
+#token Timeout("timeout") "timeout"
+#token Inventory("inventory") "inventory"
+#token StringToken("STRING_TOKEN") "STRING_TOKEN"
+#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP"
+#token Struct("struct") "struct"
+#token Uint64("UINT64") "UINT64"
+#token Uint32("UINT32") "UINT32"
+#token Uint16("UINT16") "UINT16"
+#token Char16("CHAR16") "CHAR16"
+#token Uint8("UINT8") "UINT8"
+#token Guid("guid") "guid"
+#token CheckBox("checkbox") "checkbox"
+#token EndCheckBox("endcheckbox") "endcheckbox"
+#token Numeric("numeric") "numeric"
+#token EndNumeric("endnumeric") "endnumeric"
+#token Minimum("minimum") "minimum"
+#token Maximum("maximum") "maximum"
+#token Step("step") "step"
+#token Default("default") "default"
+#token Password("password") "password"
+#token EndPassword("endpassword") "endpassword"
+#token String("string") "string"
+#token EndString("endstring") "endstring"
+#token MinSize("minsize") "minsize"
+#token MaxSize("maxsize") "maxsize"
+#token Encoding("encoding") "encoding"
+#token SuppressIf("suppressif") "suppressif"
+#token Hidden("hidden") "hidden"
+#token Goto("goto") "goto"
+#token InconsistentIf "inconsistentif"
+#token EndIf("endif") "endif"
+#token IdEqId("ideqid") "ideqid"
+#token IdEqVal("ideqval") "ideqval"
+#token VarEqVal("vareqval") "vareqval"
+#token Var("var") "var"
+#token IdEqValList("ideqvallist") "ideqvallist"
+#token Length("length") "length"
+#token Values("values") "values"
+#token Key("key") "key"
+#token DefaultFlag("DEFAULT") "DEFAULT"
+#token ManufacturingFlag("MANUFACTURING") "MANUFACTURING"
+#token InteractiveFlag("INTERACTIVE") "INTERACTIVE"
+#token NVAccessFlag("NV_ACCESS") "NV_ACCESS"
+#token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED"
+#token LateCheckFlag("LATE_CHECK") "LATE_CHECK"
+#token Class("class") "class"
+#token Subclass("subclass") "subclass"
+#token TypeDef("typedef") "typedef"
+#token Restore("restore") "restore"
+#token Save("save") "save"
+#token Defaults("defaults") "defaults"
+#token Banner("banner") "banner"
+#token Align("align") "align"
+#token Left("left") "left"
+#token Right("right") "right"
+#token Center("center") "center"
+#token Line("line") "line"
+#token VarStore("varstore") "varstore"
+#token Name("name") "name"
+#token Oem("oem") "oem"
+#token True("TRUE") "TRUE"
+#token False("FALSE") "FALSE"
+#token GreaterThan(">") ">"
+#token GreaterEqual(">=") ">="
+#token LessThan("<") "<"
+#token LessEqual("<=") "<="
+
+//
+// Define the class and subclass tokens
+//
+#token ClassNonDevice("NONDEVICE") "NON_DEVICE"
+#token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE"
+#token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE"
+#token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE"
+#token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE"
+#token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE"
+#token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE"
+
+#token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION"
+#token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION"
+#token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE"
+#token SubclassSingleUse("SINGLE_USE") "SINGLE_USE"
+
+#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters
+#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*"
+#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+"
+#token OpenBrace("{") "\{"
+#token CloseBrace("}") "\}"
+#token OpenParen("(") "\("
+#token CloseParen(")") "\)"
+#token OpenBracket("[") "\["
+#token CloseBracket("]") "\]"
+
+//
+// Define all other invalid characters so that they get through the lexical phase
+// and we can catch them during the parse phase. We get much better error
+// messages then.
+//
+#token InvalidCharacters("invalid characters") "~[;:=,\.\|]"
+
+//
+// This is the overall definition of a VFR form definition script.
+//
+program :
+ ( dataStructDefinition )*
+ formSetStatement
+ ( vfrStatementVarStore )*
+ ( formDefinition )*
+ EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>
+ "@" // end of file
+ ;
+
+formSetStatement :
+ FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>
+ Guid "="
+ OpenBrace
+ G1:Number ","
+ G2:Number ","
+ G3:Number ","
+ OpenBrace
+ G4:Number ","
+ G5:Number ","
+ G6:Number ","
+ G7:Number ","
+ G8:Number ","
+ G9:Number ","
+ G10:Number ","
+ G11:Number
+ CloseBrace
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()
+ );
+ >>
+ ","
+ Title "=" getStringId ","
+ Help "=" getStringId ","
+ //
+ // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)
+ //
+ << WriteDWord (0, 0); WriteDWord (0, 0); >>
+ Class "=" CVAL:classDefinition "," << WriteClass (); >>
+ Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >>
+ << WriteWord (mNvDataStructSize); >>
+ ;
+
+//
+// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C
+//
+classDefinition :
+ validClassNames ( "\|" validClassNames )*
+ ;
+
+validClassNames :
+ CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>
+ | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>
+ | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>
+ | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>
+ | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>
+ | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>
+ | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>
+ | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>
+
+//
+// A form can only be of one subclass type.
+//
+subclassDefinition :
+ SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>
+ | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>
+ | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>
+ | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>
+ | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>
+
+//
+// Parse a C type data structure for storing VFR setup data. Allow:
+// typedef struct _XXX_ {
+// (fields)
+// } MY_NV_DATA;
+//
+dataStructDefinition :
+ << int IsNonNV = 0; >>
+ { TypeDef }
+ S:Struct
+ (
+ NonNvDataMap << IsNonNV = 1; >>
+ |
+ { StringIdentifier }
+ ) << StartStructDefinition (IsNonNV, S->getLine()); >>
+ OpenBrace
+ dataStructFields
+ CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >>
+ ";"
+ ;
+
+//
+// Parse a C type data structure for defining data that is not stored in NV.
+// typedef struct _NON_NV_DATA_MAP {
+// (fields)
+// } NON_NV_DATA_MAP;
+//
+nonNvDataStructDefinition :
+ { TypeDef }
+ Struct NonNvDataMap
+ { StringIdentifier }
+ OpenBrace
+ dataStructFields
+ CloseBrace NAME:StringIdentifier << AddStructField (NAME->getText(), NAME->getLine(), 0, 0, 0); >>
+ ";"
+ ;
+
+dataStructFields :
+ ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT64 Name[4];
+// UINT64 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField64 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT64"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT32 Name[4];
+// UINT32 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField32 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT32"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT16 Name[4];
+// UINT16 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField16 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ ( "UINT16" | "CHAR16" )
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT8 Name[4];
+// UINT8 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField8 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT8"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// form formid = 1,
+// title = STRING_TOKEN(STR_FORM_TITLE);
+// -- form statements --
+// endform;
+//
+// The Form ID cannot be 0
+//
+formDefinition :
+ FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >>
+ "="
+ VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>
+ ","
+ Title "=" getStringId ";" // writes string identifier
+ ( vfrStatements )*
+ ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>
+ ;
+
+//
+// VFR statements in a formset
+//
+vfrStatements :
+ vfrStatementSubTitle |
+ vfrStatementOneOf |
+ vfrStatementTextText |
+ vfrStatementCheckBox |
+ vfrStatementNumeric |
+ vfrStatementDate |
+ vfrStatementTime |
+ vfrStatementPassword |
+ vfrStatementString |
+ vfrStatementSuppressIf |
+ vfrStatementHidden |
+ vfrStatementGoto |
+ vfrStatementGrayOutIf |
+ vfrStatementInconsistentIf |
+ vfrStatementLabel |
+ vfrStatementBanner |
+ vfrStatementInventory |
+ vfrStatementOrderedList |
+ vfrStatementOem |
+ vfrStatementSaveRestoreDefaults
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// label 100;
+//
+vfrStatementLabel :
+ OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>
+ VAL:Number <<
+ WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
+ AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
+ >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// oem 0x12, 0x34, 0x56;
+//
+vfrStatementOem :
+ OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>
+ ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )
+ ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// inconsistentif NOT .... AND NOT .... OR ... endif;
+//
+vfrStatementInconsistentIf :
+ << ResetFlags (); >>
+ IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>
+ Prompt "=" getStringId ","
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR
+// ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND
+// (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR
+// vareqval var(VAR_EQ_TEST_NAME) == 0x1)
+//
+// For supporting complex express, divide the vfrBooleanExpression to two parts
+// so that pred-LL(k) parser can parse incrementally.
+//
+vfrBooleanExpression :
+ leftPartVfrBooleanExp { rightPartVfrBooleanExp }
+ ;
+
+leftPartVfrBooleanExp :
+ OpenParen vfrBooleanExpression CloseParen |
+ (ideqval | ideqid | ideqvallist | vareqval | truefalse) |
+ NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ;
+
+rightPartVfrBooleanExp :
+ AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> |
+ OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// TRUE
+//
+truefalse :
+ TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |
+ FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};
+//
+vfrStatementVarStore :
+ OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>
+ STRUCT_NAME:StringIdentifier ","
+ Key "=" KNUM:Number ","
+ Name "=" VAR_NAME:StringIdentifier ","
+ Guid "="
+ OpenBrace
+ G1:Number ","
+ G2:Number ","
+ G3:Number ","
+ OpenBrace
+ G4:Number ","
+ G5:Number ","
+ G6:Number ","
+ G7:Number ","
+ G8:Number ","
+ G9:Number ","
+ G10:Number ","
+ G11:Number
+ CloseBrace
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()
+ );
+ WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2));
+ AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());
+ >>
+
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// vareqval var(0x100) == 0x20
+//
+vareqval :
+ OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>
+ Var OpenParen
+ VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>
+ CloseParen
+ compareNumber
+ ;
+
+ideqval :
+ OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>
+ vfrStructFieldName[0]
+ compareNumber
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// ideqid MyNVData3.Field16A == MyNVData3.Field16B
+//
+// NOTE: Before processing the second variable store in the ideqid statement, set a global flag
+// so that when we parse the second variable we set the secondary variable store id.
+//
+ideqid :
+ OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >>
+ vfrStructFieldName[0]
+ compareVfrStructFieldNameNL0
+ ;
+
+//*****************************************************************************
+//
+// compareNumber is the combination of compare operation and Number
+//
+compareNumber :
+ (
+ "=="
+ VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>
+ ) |
+ (
+ GTOPID:GreaterThan
+ VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
+ ) |
+ (
+ GEOPID:GreaterEqual
+ VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
+ ) |
+ (
+ LTOPID:LessThan
+ VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ) |
+ (
+ LEOPID:LessEqual
+ VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
+ )
+ ;
+
+//*****************************************************************************
+//
+// compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0]
+//
+compareVfrStructFieldNameNL0 :
+ (
+ "==" << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >>
+ ) |
+ (
+ GTOPID:GreaterThan << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
+ ) |
+ (
+ GEOPID:GreaterEqual << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
+ ) |
+ (
+ LTOPID:LessThan << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ) |
+ (
+ LEOPID:LessEqual << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
+ )
+ ;
+
+
+ideqvallist :
+ OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>
+ vfrStructFieldName[0]
+ "=="
+ ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +
+ << FlushQueueIdEqValList(); >>
+ ;
+
+vfrStatementGoto :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
+ AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
+ >>
+ KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >>
+ Help "=" getStringId
+ {
+ ","
+ FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ }
+ {
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ ";"
+ ;
+
+vfrStatementHidden :
+ IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>
+ Value "="
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>
+ Key "="
+ KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// suppressif <boolean_expression> { grayoutif } <statements>+ endif;
+// Note:
+// You can have: suppressif:grayoutif:statements:endif
+// suppressif:grayoutif:endif -- serves no purpose
+// suppressif:statements:endif
+// suppressif:endif -- serves no purpose
+//
+vfrStatementSuppressIf :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+//
+// This is the form for a grayoutif nested in a suppressif statement
+//
+suppressIfGrayOutIf :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// grayoutif { flags = n, } <boolean_expression> endif;
+// Note:
+// You can have: grayoutif:suppressif:statements:endif
+// grayoutif:statements:endif
+//
+//
+vfrStatementGrayOutIf :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+//
+// This is the format for a suppressif nested in a grayoutif
+//
+grayoutIfSuppressIf :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ ;
+
+//
+// These are the VFR statements that are valid inside a suppressif or grayoutif statement.
+//
+suppressIfAndGrayoutIfSubstatements :
+ vfrStatementOneOf |
+ vfrStatementTextText |
+ vfrStatementCheckBox |
+ vfrStatementNumeric |
+ vfrStatementDate |
+ vfrStatementTime |
+ vfrStatementPassword |
+ vfrStatementString |
+ vfrStatementHidden |
+ vfrStatementGoto |
+ vfrStatementLabel |
+ vfrStatementInventory |
+ vfrStatementOrderedList |
+ vfrStatementSaveRestoreDefaults
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// password varid = MyNvData.Password,
+// prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+// help = STRING_TOKEN(STR_PASSWORD_HELP),
+// minsize = 6,
+// maxsize = 20,
+// encoding = 1,
+// endpassword;
+
+vfrStatementPassword :
+ << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>
+ VarId "=" vfrStructFieldNameArray[0] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
+ Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>
+ EndPassword ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// string varid = MyNv.String,
+// prompt = STRING_TOKEN(STR_STRING_PROMPT),
+// help = STRING_TOKEN(STR_STRING_HELP),
+// flags = INTERACTIVE,
+// key = 0x1234,
+// minsize = 6,
+// maxsize = 0x14,
+// endstring;
+//
+// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error
+// reporting we save the line number of the "help" keyword.
+//
+vfrStatementString :
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>
+ VarId "=" vfrStructFieldNameArray[0] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "="
+ flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ ","
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
+ EndString ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// numeric varid = MyIfrNVData.HowOldAreYouInYears,
+// prompt = STRING_TOKEN(STR_NUMERIC_PROMPT),
+// help = STRING_TOKEN(STR_NUMERIC_HELP),
+// flags = INTERACTIVE, // flags is optional
+// key = 0x1234, // key is optional if (flags & INTERACTIVE = 0)
+// minimum = 0x0,
+// maximum = 0xf0,
+// step = 1, // step is option, and step=1 if not specified
+// default = 0; // default is optional, and default=minimum if not specified
+// endnumeric;
+//
+// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.
+// That check is done in WriteFlagsKey() function.
+//
+vfrStatementNumeric :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>
+ VarId "=" vfrStructFieldName[2] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >>
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ minMaxStepDefault
+ EndNumeric ";" << WriteMinMaxStepDefault (); >>
+ ;
+
+//
+// Parse minimum/maximum/step/default statements. Special cases:
+// - if step not specified, then the value is 1
+// - if default not specified, then the value is the min value specified
+// - if max < min, print a warning and swap the values (changes default too)
+//
+minMaxStepDefault :
+ << InitMinMaxStepDefault (); >>
+ Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >>
+ Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >>
+ { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }
+ { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> }
+ ;
+
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// date year varid = Date.Year, // "Date.Year" is a special case we recognize
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_YEAR_HELP),
+// minimum = 1939,
+// maximum = 2101,
+// step = 1,
+// default = 1964,
+//
+// month varid = Date.Month,
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_MONTH_HELP),
+// minimum = 1,
+// maximum = 12,
+// step = 1,
+// default = 1,
+//
+// day varid = Date.Day,
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_DAY_HELP),
+// minimum = 1,
+// maximum = 31,
+// step = 0x1,
+// default = 1,
+//
+// enddate;
+//
+vfrStatementDate :
+ Date
+ IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ EndDate ";"
+ ;
+
+vfrStatementTime :
+ Time
+ IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ EndTime ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// text text = STRING_ID;
+// text text = STRING_ID, text = STRING_ID;
+// text text = STRING_ID, text = STRING_ID, flags = x, key = y;
+//
+vfrStatementTextText :
+ << ResetFlags (); >>
+ IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>
+ Help "=" getStringId ","
+ Text "="
+ getStringId // writes string identifier
+ { "," Text "=" getStringId
+ "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >>
+ ","
+ Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>
+ }
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// inventory help = ID, text = ID;
+// inventory help = ID, text = id, text = ID;
+//
+vfrStatementInventory :
+ IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>
+ Help "=" getStringId ","
+ Text "=" getStringId // writes string identifier
+ { "," Text "=" getStringId
+ }
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// restore defaults,
+// formid = 4,
+// prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
+// help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
+// flags = 0,
+// key = 0;
+//
+// save defaults,
+// formid = 4,
+// prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+// help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
+// flags = 0,
+// key = 0;
+//
+vfrStatementSaveRestoreDefaults :
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>
+ | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>
+ )
+ Defaults ","
+ FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2));
+ AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());
+ >>
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId << LineNum = KH->getLine(); >>
+ {
+ "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ }
+ {
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
+//
+//
+flagsField :
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
+ | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >>
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
+ ;
+
+dateTimeSubStatement :
+ Prompt "=" getStringId ","
+ Help "=" getStringId ","
+ << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
+ minMaxStepDefault << WriteMinMaxStepDefault (); >>
+ ;
+
+vfrStatementCheckBox :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>
+ VarId "=" vfrStructFieldName[1] ","
+ Prompt "=" getStringId ","
+ Help "=" getStringId ","
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
+ {
+ Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ EndCheckBox ";"
+ ;
+
+vfrStatementSubTitle :
+ IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>
+ getStringId // writes string indentifier
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// banner
+// title = STRING_TOKEN(STR_BANNER_TITLE),
+// line 1,
+// align center; // or left or right
+//
+// banner,
+// title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;
+//
+vfrStatementBanner :
+ IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>
+ Title "=" getStringId ","
+ (
+ Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>
+ Align
+ ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>
+ | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>
+ | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>
+ ) ";"
+ |
+ Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>
+ << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>
+ )
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// oneof varid = MyNv.OneOfData,
+// prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+// help = STRING_TOKEN(STR_ONE_OF_HELP),
+// option text = STRING_TOKEN(STR_ONE_OF_TEXT),
+// value = 0,
+// flags = DEFAULT | INTERACTIVE;
+//
+// supressif/grayoutif are supported inside oneof stmt.
+// We do not restrict the number of oneOfOptionText to >=2, but >=1.
+// The situation that all oneOfOptionText are suppressed is also possiable.
+//
+vfrStatementOneOf :
+ << ResetFlags (); >>
+ IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>
+ VarId "=" vfrStructFieldName[2] ","
+ Prompt "=" getStringId "," // writes string identifier
+ Help "=" getStringId "," // writes string identifier
+ ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2.
+ IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// orderedlist varid = MyNv.OrderedListData,
+// prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),
+// help = STRING_TOKEN(STR_ORDERED_LIST_HELP),
+// option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;
+// -- additional option text --
+// endlist;
+//
+vfrStatementOrderedList :
+ << ResetFlags (); InitOrderedList(); >>
+ IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>
+ VarId "=" vfrStructFieldNameArray[1] ","
+ Prompt "=" getStringId "," // writes string identifier
+ Help "=" getStringId "," // writes string identifier
+ orderedListOptionText ( orderedListOptionText )+
+ IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
+//
+// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to
+// be set, and value cannot be 0.
+//
+orderedListOptionText :
+ << UINT32 KeyValue = 0; >>
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
+ Text "=" getStringId "," // writes string identifier
+ Value "=" WVAL:Number "," <<
+ if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {
+ PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL);
+ } else {
+ WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2));
+ }
+ >>
+ FF:Flags "=" orderedListFlagsField
+ ("\|" orderedListFlagsField )*
+ {
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
+ }
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>
+ ";" << mOptionCount++; >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
+//
+// The ordered list flags field cannot have a default.
+//
+orderedListFlagsField :
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
+ | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>
+ ;
+
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field".
+// This implementation is specific to strings, passwords, and references in an
+// ordered list statement because we want to specify the size of the entire
+// field, rather than just one element. Then call a function to write out its
+// offset and length.
+//
+vfrStructFieldNameArray[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (1,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 1
+ );
+ >>
+ ;
+
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field",
+// then call a function to write out its offset and length.
+//
+vfrStructFieldName[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (1,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 0
+ );
+ >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// MyNvStructure.FieldName[4]
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field",
+// then call a function to write out the offset with no length.
+//
+vfrStructFieldNameNL[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (0,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 0
+ );
+ >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// suppressif TRUE OR FALSE;
+// grayoutif FALSE OR TRUE;
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
+// option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;
+// endif;
+//
+oneOfOptionText :
+ suppressIfOptionText |
+ grayOutIfOptionText |
+ commonOptionText
+ ;
+
+suppressIfOptionText :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { suppressIfGrayOutIf } ( commonOptionText )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+grayOutIfOptionText :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { grayoutIfSuppressIf } ( commonOptionText )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+commonOptionText :
+ << UINT32 KeyValue = 0; >>
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
+ Text "=" getStringId "," // writes string identifier
+ Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>
+ FF:Flags "=" flagsField ("\|" flagsField )*
+ {
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
+ }
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>
+ ";" << mOptionCount++; >>
+ ;
+
+//
+// Gets a string identifier. It must be a numeric value of form:
+//
+// STRING_TOKEN(100)
+//
+getStringId :
+ << unsigned short StrId; >>
+ StringToken OpenParen
+ IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >>
+ CloseParen
+ ;
+
+//******************************************************************************
+//
+// Parser class definition.
+//
+class EfiVfrParser {
+<<
+//
+// Parser definitions go here
+//
+private:
+ STRUCT_DEFINITION *mFirstStructDefinition;
+ STRUCT_DEFINITION *mLastStructDefinition;
+ INT32 mNvDataStructSize;
+ INT32 mNonNvDataStructSize;
+ //
+ // Flag to indicate that we're processing a ideqid VFR statement so that
+ // we can do late checks on the statement.
+ //
+ INT32 mIdEqIdStmt;
+ INT32 mLastNVVariableDataSize;
+ GOTO_REFERENCE *mGotoReferences;
+ FORM_ID_VALUE *mFormIdValues;
+ VfrOpcodeHandler mOpcodeHandler;
+ UINT16_LIST *mUint16List;
+ UINT16_LIST *mLastUint16;
+ UINT16_LIST *mDefinedLabels;
+ UINT16_LIST *mDefinedVarStoreId;
+ UINT16_LIST *mLastDefinedVarStoreId;
+ UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;
+ UINT32 mStmtFlags;
+ UINT32 mSubStmtFlags;
+ UINT32 mSubStmtFlagsLineNum;
+ EFI_GUID mFormSetGuid;
+ UINT8 mNvDataStructDefined;
+ UINT16 mClass, mSubclass;
+ UINT32 mIfStart;
+ UINT32 mOptionCount; // how many "option" fields in a given statement
+ UINT32 mLastVarIdSize;
+ UINT8 mOutput;
+public:
+
+VOID
+EfiVfrParser::SetIfStart (
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when an "if" is encountered. Save the
+ source line number so we can point to it if we don't find a
+ corresponding endif later.
+
+Arguments:
+ LineNum - source line number where the "if" was parsed.
+
+Returns:
+ None
+
+--*/
+{
+ mIfStart = LineNum;
+}
+VOID
+EfiVfrParser::SetClass (
+ UINT32 LineNum,
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when a "class" statement is found. Check the
+ range on the class value and save it for later.
+
+Arguments:
+ LineNum - source line number where the class statement was parsed.
+ Value - the class value
+
+Returns:
+ None
+
+--*/
+{
+ if (Value & 0xFFFF0000) {
+ PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
+ }
+ mClass |= (UINT16)Value;
+}
+VOID
+EfiVfrParser::SetSubclass (
+ UINT32 LineNum,
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when a subclass statement is found. Check the
+ range on the value and save it for later.
+
+Arguments:
+ LineNum - source line number where the class statement was parsed.
+ Value - the subclass value from the VFR statement
+
+Returns:
+ None
+
+--*/
+{
+ if (Value & 0xFFFF0000) {
+ PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
+ }
+ mSubclass |= (UINT16)Value;
+}
+VOID EfiVfrParser::WriteClass ()
+{
+ WriteWord (mClass);
+ mClass = 0;
+}
+VOID EfiVfrParser::WriteSubclass ()
+{
+ WriteWord (mSubclass);
+ mSubclass = 0;
+}
+VOID EfiVfrParser::WriteIfrBytes ()
+{
+ mOpcodeHandler.WriteIfrBytes ();
+}
+VOID
+EfiVfrParser::WriteFlagsKey (
+ UINT32 KeyValue,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Write out the flags and key values from the previous VFR statement.
+ Many statements take a flags/key pair. If not specified, then 0
+ values are written out. However do not allow an interactive flags field
+ to be specified if no key value is specified. Also, if NV_ACCESS flag
+ is set but INTERACTIVE is not, then set interactive and issue a warning.
+
+Arguments:
+ KeyValue - the key value from the VFR statement
+ LineNum - source line number where the statement was parsed
+
+Returns:
+ None
+
+--*/
+{
+ if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {
+ PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");
+ }
+ if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {
+ PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");
+ mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;
+ }
+ WriteFlags ();
+ WriteWord (KeyValue);
+}
+VOID
+EfiVfrParser::InitOrderedList ()
+{
+ mOptionCount = 0;
+}
+VOID
+EfiVfrParser::EndOrderedList (
+ UINT32 LineNum
+ )
+{
+ if (mLastVarIdSize < mOptionCount) {
+ PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
+ }
+}
+VOID
+EfiVfrParser::ResetFlags ()
+/*++
+
+Routine Description:
+
+ Flags are set for each substatement in a given one-of statement.
+ To make sure there are no conflicts, for example setting DEFAULT on
+ more than one substatement, we keep track of the flags at a statement
+ level and a substatement level. This function resets the flags so
+ we get a fresh start.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ mStmtFlags = 0;
+ mSubStmtFlagsLineNum = 0;
+ mSubStmtFlags = 0;
+}
+//
+// Test validity of flags value for a one-of statement.
+//
+VOID
+EfiVfrParser::TestOneOfFlags (
+ UINT32 LineNum
+ )
+{
+ //
+ // One of the fields must have had the default bit set
+ //
+ if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {
+ PrintWarningMessage (LineNum, "default value must be specified", NULL);
+ }
+}
+VOID
+EfiVfrParser::SetFlags (
+ UINT32 Flags,
+ UINT32 LineNum
+ )
+{
+ //
+ // Check for redefinitions and invalid combinations
+ //
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {
+ PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");
+ }
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {
+ PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");
+ }
+ mSubStmtFlags |= Flags;
+ mSubStmtFlagsLineNum = LineNum;
+}
+VOID
+EfiVfrParser::WriteFlags ()
+{
+ //
+ // Check value for validity
+ //
+ if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT |
+ EFI_IFR_FLAG_MANUFACTURING |
+ EFI_IFR_FLAG_INTERACTIVE |
+ EFI_IFR_FLAG_NV_ACCESS |
+ EFI_IFR_FLAG_RESET_REQUIRED |
+ EFI_IFR_FLAG_LATE_CHECK )) {
+ PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);
+ }
+ WriteByte ((UINT8)mSubStmtFlags, 'F');
+ //
+ // We can now clear the substatement flags
+ //
+ mStmtFlags |= mSubStmtFlags;
+ mSubStmtFlags = 0;
+}
+//
+// When we parse a min/max/step/default sequence, save off the values for
+// later use. Call this first to init the values.
+//
+VOID
+EfiVfrParser::InitMinMaxStepDefault ()
+{
+ mMinimumValue = 0;
+ mMaximumValue = 0;
+ mStepValue = 1;
+ mDefaultValue = 0;
+}
+VOID
+EfiVfrParser::WriteMinMaxStepDefault ()
+{
+ WriteWord (mMinimumValue);
+ WriteWord (mMaximumValue);
+ WriteWord (mStepValue);
+ WriteWord (mDefaultValue);
+}
+VOID
+EfiVfrParser::SetMinMaxStepDefault (
+ UINT16 Value,
+ INT32 MMSD,
+ INT32 LineNum
+ )
+{
+ UINT16 TempValue;
+ //
+ // Min specified
+ //
+ if (MMSD == 0) {
+ mMinimumValue = Value;
+ mDefaultValue = Value;
+ //
+ // Max specified
+ //
+ } else if (MMSD == 1) {
+ mMaximumValue = Value;
+ //
+ // If min > max, then swap the values. That includes resetting the default
+ // value as well.
+ //
+ if (mMinimumValue > mMaximumValue) {
+ PrintWarningMessage (LineNum, NULL, "maximum < minimum");
+ TempValue = Value;
+ mMaximumValue = mMinimumValue;
+ mMinimumValue = TempValue;
+ mDefaultValue = mMinimumValue;
+ }
+ //
+ // Step specified
+ //
+ } else if (MMSD == 2) {
+ mStepValue = Value;
+ //
+ // Default specified. Make sure min <= default <= max.
+ //
+ } else if (MMSD == 3) {
+ mDefaultValue = Value;
+ if (mMinimumValue > Value) {
+ PrintErrorMessage (LineNum, NULL, "default value < minimum value");
+ } else if (Value > mMaximumValue) {
+ PrintErrorMessage (LineNum, NULL, "default value > maximum value");
+ }
+ } else {
+ PrintErrorMessage (LineNum, "application error", "internal MMSD error");
+ }
+}
+VOID
+EfiVfrParser::AddLabel (
+ UINT32 LabelNumber,
+ UINT32 LineNum
+ )
+{
+ UINT16_LIST *Label;
+
+ //
+ // Added a label from the user VFR script. Make sure they haven't already
+ // defined the same label elsewhere
+ //
+ for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {
+ if (Label->Value == LabelNumber) {
+ PrintErrorMessage (LineNum, NULL, "label already defined");
+ PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");
+ break;
+ }
+ }
+ Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
+ if (Label == NULL) {
+ PrintErrorMessage (0, NULL, "memory allocation error");
+ return;
+ }
+ memset ((char *)Label, 0, sizeof (UINT16_LIST));
+ Label->Value = LabelNumber;
+ Label->LineNum = LineNum;
+ Label->Next = mDefinedLabels;
+ mDefinedLabels = Label;
+}
+VOID
+EfiVfrParser::QueueIdEqValList (
+ UINT16 Value
+ )
+{
+ UINT16_LIST *U16;
+
+ U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
+ if (U16 == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");
+ } else {
+ memset ((char *)U16, 0, sizeof (UINT16_LIST));
+ U16->Value = Value;
+ if (mUint16List == NULL) {
+ mUint16List = U16;
+ } else {
+ mLastUint16->Next = U16;
+ }
+ mLastUint16 = U16;
+ }
+}
+VOID
+EfiVfrParser::FlushQueueIdEqValList ()
+{
+ UINT32 Count;
+
+ //
+ // We queued up a list of IdEqValList items. The IFR requires a count
+ // followed by the actual values. Do it.
+ //
+ Count = 0;
+ mLastUint16 = mUint16List;
+ while (mLastUint16 != NULL) {
+ Count++;
+ mLastUint16 = mLastUint16->Next;
+ }
+ // BUGBUG -- check for more than 16K items?
+ WriteWord (Count);
+ //
+ // Now write the values.
+ //
+ mLastUint16 = mUint16List;
+ while (mLastUint16 != NULL) {
+ WriteWord ((UINT32)mLastUint16->Value);
+ mLastUint16 = mLastUint16->Next;
+ }
+ //
+ // Free up the list
+ //
+ mLastUint16 = mUint16List;
+ while (mUint16List != NULL) {
+ mLastUint16 = mUint16List->Next;
+ free (mUint16List);
+ mUint16List = mLastUint16;
+ }
+}
+VOID
+EfiVfrParser::PrintErrorMessage (
+ UINT32 LineNum,
+ CHAR8 *Msg1,
+ CHAR8 *Msg2
+ )
+{
+ char *FileName;
+
+ if (LineNum != 0) {
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ Error (FileName, LineNum, 0, Msg1, Msg2);
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);
+ }
+}
+VOID
+EfiVfrParser::PrintWarningMessage (
+ UINT32 LineNum,
+ CHAR8 *Msg1,
+ CHAR8 *Msg2
+ )
+{
+ char *FileName;
+
+ if (LineNum != 0) {
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ Warning (FileName, LineNum, 0, Msg1, Msg2);
+ } else {
+ Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);
+ }
+}
+VOID
+EfiVfrParser::syn (
+ ANTLRAbstractToken *Tok,
+ ANTLRChar *Egroup,
+ SetWordType *Eset,
+ ANTLRTokenType ETok,
+ INT32 Huh
+ )
+/*++
+
+Routine Description:
+ Called by the parser base class as a result of parse syntax errors.
+
+Arguments:
+ Tok - token that caused the error
+ Egroup - not sure
+ Eset - index in token table of the expected token
+ Huh - not sure
+
+Returns:
+ NA
+
+--*/
+{
+ char *FileName;
+ UINT32 LineNum;
+
+ LineNum = Tok->getLine ();
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ //
+ // Sometimes the token number is 0, in which case I don't know what to
+ // print.
+ //
+ if (ETok == 0) {
+ Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");
+ } else {
+ //
+ // If we were expecting an endif, then report the line where the corresponding
+ // IF began.
+ //
+ if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {
+ LineNum = mIfStart;
+ FileName = ConvertLineNumber (&LineNum);
+ Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);
+ } else {
+ Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);
+ }
+ }
+}
+
+VOID
+EfiVfrParser::init()
+/*++
+
+Routine Description:
+ Initializations function for our parser.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ ANTLRParser::init();
+
+ //
+ // Used for queuing a variable list of UINT16's
+ //
+ mUint16List = NULL;
+ mLastUint16 = NULL;
+ mFirstStructDefinition = NULL;
+ mLastStructDefinition = NULL;
+ mNvDataStructSize = 0;
+ mNonNvDataStructSize = 0;
+ mNvDataStructDefined = 0;
+ mGotoReferences = NULL;
+ mFormIdValues = NULL;
+ mDefinedLabels = NULL;
+ mClass = 0;
+ mSubclass = 0;
+ mIfStart = 0;
+ mDefinedVarStoreId = NULL;
+ mLastDefinedVarStoreId = NULL;
+ mIdEqIdStmt = 0;
+ mLastNVVariableDataSize = 0;
+
+ memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));
+}
+//
+// Destructor for the parser.
+//
+EfiVfrParser::~EfiVfrParser(VOID)
+{
+ Cleanup();
+}
+VOID
+EfiVfrParser::Cleanup (VOID)
+/*++
+
+Routine Description:
+ Free memory allocated during parsing
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *NextStruct;
+ STRUCT_FIELD_DEFINITION *NextField;
+ UINT8 Buff[6];
+ UINT16_LIST *NextU16List;
+
+ //
+ // Free up the structure definitions if any
+ //
+ while (mFirstStructDefinition != NULL) {
+ //
+ // Free up all the fields for this struct
+ //
+ while (mFirstStructDefinition->Field != NULL) {
+ NextField = mFirstStructDefinition->Field->Next;
+ free (mFirstStructDefinition->Field->Name);
+ free (mFirstStructDefinition->Field);
+ mFirstStructDefinition->Field = NextField;
+ }
+ NextStruct = mFirstStructDefinition->Next;
+ free (mFirstStructDefinition->Name);
+ free (mFirstStructDefinition);
+ mFirstStructDefinition = NextStruct;
+ }
+ //
+ // Free up the goto references and form id defines
+ //
+ FreeGotoReferences ();
+ //
+ // Free up label list
+ //
+ while (mDefinedLabels != NULL) {
+ NextU16List = mDefinedLabels->Next;
+ delete (mDefinedLabels);
+ mDefinedLabels = NextU16List;
+ }
+ //
+ // Free up the list of defined variable storage IDs
+ //
+ while (mDefinedVarStoreId != NULL) {
+ NextU16List = mDefinedVarStoreId->Next;
+ delete (mDefinedVarStoreId);
+ mDefinedVarStoreId = NextU16List;
+ }
+}
+
+INT32
+EfiVfrParser::AtoX (
+ CHAR8 *HexString,
+ INT32 NumBytes,
+ UINT32 *HexValue
+ )
+/*++
+
+Routine Description:
+ Given a pointer to a ascii hex string, convert to a number with the given
+ number of bytes.
+
+Arguments:
+ HexString - pointer to a string of format 30BCA
+ Size - number of bytes to convert
+ HexValue - return result
+
+Returns:
+ The number of bytes converted.
+
+--*/
+{
+ INT32 Count;
+ INT32 Value;
+
+ *HexValue = 0;
+ Count = 0;
+ while (Count < NumBytes) {
+ if ((*HexString >= '0') && (*HexString <= '9')) {
+ Value = *HexString - '0';
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
+ Value = *HexString - 'a' + 10;
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
+ Value = *HexString - 'A' + 10;
+ } else {
+ return Count;
+ }
+ HexString++;
+ *HexValue = (*HexValue << 4) | Value;
+ if ((*HexString >= '0') && (*HexString <= '9')) {
+ Value = *HexString - '0';
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
+ Value = *HexString - 'a' + 10;
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
+ Value = *HexString - 'A' + 10;
+ } else {
+ return Count;
+ }
+ *HexValue = (*HexValue << 4) | Value;
+ HexString++;
+ Count++;
+ }
+ return Count;
+}
+VOID
+EfiVfrParser::WriteGuidValue (
+ UINT32 TokenLineNum,
+ CHAR8 *G1,
+ CHAR8 *G2,
+ CHAR8 *G3,
+ CHAR8 *G4,
+ CHAR8 *G5,
+ CHAR8 *G6,
+ CHAR8 *G7,
+ CHAR8 *G8,
+ CHAR8 *G9,
+ CHAR8 *G10,
+ CHAR8 *G11
+ )
+/*++
+
+Routine Description:
+ A Guid was parsed, likely of format:
+ #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }
+
+ Write out the value.
+
+Arguments:
+ TokenLineNum - line number where the guid was used
+ G1-G11 - the 11 fields of the guid value
+
+Returns:
+ None.
+
+--*/
+{
+ UINT32 Value;
+ INT32 Loop;
+
+ mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);
+ mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);
+ mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);
+ mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);
+ mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);
+ mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);
+ mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);
+ mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);
+ mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);
+ mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);
+ mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);
+
+ WriteDWord (mFormSetGuid.Data1, 'G');
+ WriteWord (mFormSetGuid.Data2);
+ WriteWord (mFormSetGuid.Data3);
+ WriteByte (mFormSetGuid.Data4[0], 0);
+ WriteByte (mFormSetGuid.Data4[1], 0);
+ WriteByte (mFormSetGuid.Data4[2], 0);
+ WriteByte (mFormSetGuid.Data4[3], 0);
+ WriteByte (mFormSetGuid.Data4[4], 0);
+ WriteByte (mFormSetGuid.Data4[5], 0);
+ WriteByte (mFormSetGuid.Data4[6], 0);
+ WriteByte (mFormSetGuid.Data4[7], 0);
+}
+VOID
+EfiVfrParser::WriteFieldOffset (
+ INT8 WriteLength,
+ CHAR8 *StructName,
+ INT32 LineNum1,
+ CHAR8 *FieldName,
+ INT32 LineNum2,
+ INT32 ArrayIndex,
+ INT8 IsArrayIndex,
+ INT32 FieldWidth,
+ INT8 WriteArraySize
+ )
+/*++
+
+Routine Description:
+ A VFR script referenced the NV store structure. Given the structure's name
+ and the field's name, write the offset of the field to the output file.
+
+Arguments:
+ WriteLength - write the field length byte out
+ StructName - name of the NV store structure
+ LineNum1 - line number in the VFR where we are (for error printing)
+ FieldName - the name of the field within the NV store structure
+ LineNum2 - line number in the VFR where FieldName is referenced
+ ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex]
+ IsArrayIndex - non-zero if an array index was specified
+ FieldWidth - expected size for the Field (1 byte? 2 bytes?)
+ WriteArraySize - write the size of the entire field, not the size of a single element
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ UINT32 Offset;
+ UINT32 VarSize;
+ CHAR8 Msg[100];
+ //
+ // If we're writing an array size, then they better have referenced the field without an
+ // index.
+ //
+ if (WriteArraySize && IsArrayIndex) {
+ sprintf (Msg, "array index specified where an array is required");
+ PrintErrorMessage (LineNum2, FieldName, Msg);
+ return;
+ }
+ //
+ // Look through our list of known structures for a match
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ //
+ // Check for matching structure name
+ //
+ if (strcmp (StructDef->Name, StructName) == 0) {
+ //
+ // Mark it as referenced (for debug purposes only). Check the
+ // flag that indicates that we have already found a varstore VFR
+ // statement for it.
+ //
+ StructDef->Referenced++;
+ if (StructDef->VarStoreIdValid == 0) {
+ //
+ // Set it valid so we don't flag it multiple times, then emit the error
+ //
+ StructDef->VarStoreIdValid = 1;
+ PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");
+ }
+ //
+ // Let the opcode-handler know which variable storage we're now using
+ //
+ if (mIdEqIdStmt) {
+ mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);
+ } else {
+ mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);
+ }
+ //
+ // Found matching structure name. Now find the matching field name
+ //
+ for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ if (strcmp (FieldDef->Name, FieldName) == 0) {
+ //
+ // Make sure the variable size is valid
+ //
+ if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {
+ sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');
+ PrintErrorMessage (LineNum2, FieldName, Msg);
+ }
+ //
+ // If they specified an index (MyVfrData.FieldX[10]), then make sure that the
+ // data structure was declared as an array, and that the index is in bounds.
+ // If they did not specify an index, then we'll assume 0. This is required for
+ // strings.
+ //
+ if (IsArrayIndex) {
+ VarSize = FieldDef->DataSize;
+ if (FieldDef->IsArray == 0) {
+ PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");
+ return;
+ }
+ if (FieldDef->ArrayLength < ArrayIndex) {
+ PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");
+ return;
+ }
+ } else {
+ if (FieldDef->IsArray) {
+ VarSize = FieldDef->DataSize * FieldDef->ArrayLength;
+ } else {
+ VarSize = FieldDef->DataSize;
+ }
+ }
+ //
+ // If we're in the middle of a ideqid VFR statement, then this is the second
+ // variable ID that we're now processing. Make sure that its size is the same
+ // as the first variable.
+ //
+ if (mIdEqIdStmt) {
+ if (mLastVarIdSize != VarSize) {
+ PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");
+ return;
+ }
+ }
+ mLastVarIdSize = VarSize;
+ //
+ // If we're supposed to write an array size, then require it to be an array
+ //
+ if (WriteArraySize && !FieldDef->IsArray) {
+ PrintErrorMessage (LineNum2, FieldName, "array required");
+ return;
+ }
+ //
+ // Write the variable offset and size. If we're in the non-NV structure, then
+ // set the offset beyond the NV data structure size.
+ //
+ Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);
+ if (StructDef->IsNonNV) Offset += mNvDataStructSize;
+ WriteWord (Offset);
+ if (WriteLength) {
+ if (WriteArraySize) {
+ if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {
+ PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");
+ return;
+ }
+ WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);
+ } else {
+ WriteByte (FieldDef->DataSize, 0);
+ }
+ }
+ return;
+ }
+ }
+ sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);
+ PrintErrorMessage (LineNum2, Msg, NULL);
+ PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);
+ return;
+ }
+ }
+ //
+ // The structure was not found in the defined list. See if it's the "Date" structure
+ //
+ if (strcmp (StructName, "Date") == 0) {
+ //
+ // BUGBUG -- remove support for Date and Time as valid structure
+ // names. They should use the NON_NV_DATA_MAP structure for this.
+ //
+ // Someone specified Date.Years|Months|Days
+ // BUGBUG -- define some constants for the IDs used here
+ // Length == 0 implies that this is not user NV data storage.
+ //
+ if (strcmp (FieldName, "Year") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Month") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Day") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else {
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");
+ }
+ return;
+ } else if (strcmp (StructName, "Time") == 0) {
+ //
+ // Someone specified Time.Hours|Minutes|Seconds
+ // BUGBUG -- define some constants for the IDs used here
+ //
+ if (strcmp (FieldName, "Hours") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Minutes") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Seconds") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else {
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");
+ }
+ return;
+ } else {
+ PrintErrorMessage (LineNum1, StructName, "undefined structure");
+ return;
+ }
+}
+VOID
+EfiVfrParser::StartStructDefinition (
+ INT32 IsNonNV,
+ INT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Called when we encounter a new "struct _MY_STRUCT..." statement while parsing.
+ Initialize internal data and structures for parsing the fields of the structure.
+
+Arguments:
+ LineNum - line number in the source file (for error reporting purposes)
+ IsNonNv - flag indicating (if nonzero) that the variable referred to is not in
+ the standard NV store.
+Returns:
+ None
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ //
+ // Allocate memory for the structure record
+ //
+ StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));
+ memset (StructDef, 0, sizeof (STRUCT_DEFINITION));
+ StructDef->LineNum = LineNum;
+ //
+ // Set flag indicating non-NV data structure or not
+ //
+ StructDef->IsNonNV = IsNonNV;
+ //
+ // Add it to the end of our linked list. If it's the first one
+ // defined, then it's the default varstore ID, so set it valid.
+ //
+ if (mFirstStructDefinition == NULL) {
+ mFirstStructDefinition = StructDef;
+ StructDef->VarStoreIdValid = 1;
+ } else {
+ mLastStructDefinition->Next = StructDef;
+ }
+ mLastStructDefinition = StructDef;
+}
+VOID
+EfiVfrParser::EndStructDefinition (
+ CHAR8 *StructName,
+ INT32 LineNum
+ )
+{
+ STRUCT_DEFINITION *StructDef;
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ UINT32 Offset;
+ //
+ // Make sure they have not already defined a structure with this name
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {
+ PrintErrorMessage (LineNum, StructName, "structure with this name already defined");
+ //
+ // Fall through and fill in the rest of the structure information. We do
+ // this because the structure has already been added to our global list,
+ // so will be used elsewhere, so we want it to contain valid fields.
+ //
+ }
+ }
+ //
+ // Allocate memory for the structure name
+ //
+ mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);
+ strcpy (mLastStructDefinition->Name, StructName);
+ //
+ // Compute the structure size, and the offsets to each field
+ //
+ Offset = 0;
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ FieldDef->Offset = Offset;
+ Offset += FieldDef->ArrayLength * FieldDef->DataSize;
+ }
+ mLastStructDefinition->Size = Offset;
+ //
+ // Go through all the structure we have so far and figure out (if we can)
+ // the size of the non-NV storage. We also assume that the first structure
+ // definition is the primary/default storage for the VFR form.
+ //
+ if (mNonNvDataStructSize == 0) {
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (StructDef->IsNonNV) {
+ mNonNvDataStructSize = StructDef->Size;
+ break;
+ }
+ }
+ }
+ if (mNvDataStructSize == 0) {
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (StructDef->IsNonNV == 0) {
+ mNvDataStructSize = StructDef->Size;
+ break;
+ }
+ }
+ }
+}
+VOID
+EfiVfrParser::AddStructField (
+ CHAR8 *FieldName,
+ INT32 LineNum,
+ INT32 DataSize,
+ INT32 ArrayLength,
+ INT8 IsArray
+ )
+/*++
+
+Routine Description:
+ We're parsing the VFR structure definition. Add another defined field to
+ our definition.
+
+Arguments:
+ FieldName - name of the field in the structure.
+ LineNum - the line number from the input (preprocessor output) file
+ DataSize - the size of the field (1, 2, or 4 bytes)
+ ArrayLength - the number of elements (for array)
+ IsArray - non-zero if the field is an array
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ STRUCT_FIELD_DEFINITION *Temp;
+ //
+ // Make sure we don't already have a field of this name in our structure
+ //
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ if (strcmp (FieldDef->Name, FieldName) == 0) {
+ PrintErrorMessage (LineNum, FieldName, "field with this name already defined");
+ return;
+ }
+ }
+ //
+ // If it's an array, then they better not have a size of 0. For example:
+ // UINT8 MyBytes[0];
+ //
+ if (IsArray && (ArrayLength <= 0)) {
+ PrintErrorMessage (LineNum, FieldName, "invalid array size");
+ return;
+ }
+ //
+ // Allocate memory for a new structure field definition
+ //
+ FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));
+ memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));
+ FieldDef->ArrayLength = ArrayLength;
+ FieldDef->DataSize = DataSize;
+ FieldDef->IsArray = IsArray;
+ FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);
+ strcpy (FieldDef->Name, FieldName);
+ //
+ // Add it to the end of the field list for the currently active structure
+ //
+ if (mLastStructDefinition->Field == NULL) {
+ mLastStructDefinition->Field = FieldDef;
+ } else {
+ mLastStructDefinition->LastField->Next = FieldDef;
+ }
+ mLastStructDefinition->LastField = FieldDef;
+}
+VOID
+EfiVfrParser::AddVarStore (
+ CHAR8 *StructName, // actual name of the structure
+ CHAR8 *VarName, // actual NV variable name
+ UINT16 VarStoreId, // key value
+ INT32 LineNum // parse line number (for error reporting)
+ )
+/*++
+
+Routine Description:
+ Called while parsing a varstore statement. Add the variable store
+ to our linked list.
+
+Arguments:
+ StructName - the name of the typedef'ed structure to use
+ VarName - the NV variable name as specified in the varstore statement
+ VarStoreId - the variable store ID as specified in the varstore statememt
+ LineNum - the line number from the input (preprocessor output) file
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ UINT16_LIST *L16Ptr;
+ //
+ // Go through our list of previously-defined variable store IDs and
+ // make sure this one is not a duplicate in name or key value.
+ //
+ for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {
+ if (L16Ptr->Value == VarStoreId) {
+ PrintErrorMessage (LineNum, "variable storage key already used", NULL);
+ PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);
+ }
+ }
+ //
+ // Key value of 0 is invalid since that's assigned by default to the default
+ // variable store (the first structure parsed).
+ //
+ if (VarStoreId == 0) {
+ PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);
+ }
+ //
+ // Create a new element to add to the list
+ //
+ L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));
+ memset (L16Ptr, 0, sizeof (UINT16_LIST));
+ L16Ptr->LineNum = LineNum;
+ L16Ptr->Value = VarStoreId;
+ if (mDefinedVarStoreId == NULL) {
+ mDefinedVarStoreId = L16Ptr;
+ } else {
+ mLastDefinedVarStoreId->Next = L16Ptr;
+ }
+ mLastDefinedVarStoreId = L16Ptr;
+ //
+ // Find the structure definition with this name
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (strcmp (StructDef->Name, StructName) == 0) {
+ //
+ // Make sure they did not already define a variable storage ID
+ // for this structure.
+ //
+ if (StructDef->VarStoreId != 0) {
+ PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");
+ PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");
+ }
+ StructDef->VarStoreId = VarStoreId;
+ StructDef->VarStoreIdValid = 1;
+ StructDef->VarStoreLineNum = LineNum;
+ WriteWord (StructDef->Size);
+ while (*VarName) {
+ WriteByte(*VarName, 0);
+ VarName++;
+ }
+ WriteByte(0,0);
+ return;
+ }
+ }
+ PrintErrorMessage (LineNum, StructName, "structure with this name not defined");
+}
+VOID
+EfiVfrParser::WriteDWord (
+ UINT32 Value,
+ UINT8 KeyByte
+ )
+/*++
+
+Routine Description:
+ During parsing, we came upon some code that requires a 32-bit value be
+ written to the VFR binary file. Queue up the 4 bytes.
+
+Arguments:
+ Value - the 32-bit value to write
+ KeyByte - a single character which gets written out beside the first byte.
+ This is used to tag the data in the output file so that during
+ debug you have an idea what the value is.
+
+Returns:
+ None.
+
+--*/
+{
+ //
+ // Write 4 bytes, little endian. Specify a key byte only on the first one
+ //
+ mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+}
+VOID
+EfiVfrParser::WriteOpByte (
+ UINT32 LineNum,
+ UINT8 ByteValue
+ )
+/*++
+
+Routine Description:
+
+ During parsing, we came upon a new VFR opcode. At this point we flush
+ the output queue and then queue up this byte (with 'O' for opcode tag).
+
+Arguments:
+
+ ByteValue - opcode value
+
+Returns:
+
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
+}
+VOID
+EfiVfrParser::WriteByte (
+ UINT8 ByteValue,
+ UINT8 Key
+ )
+/*++
+
+Routine Description:
+
+ During parsing of the VFR we spoonfeed this function with bytes to write to
+ the output VFR binary file. This function simply queues up the bytes, and
+ the queue gets flushed each time a new VFR opcode is encountered.
+
+Arguments:
+
+ ByteValue - raw byte to write
+ Key - character to tag the byte with when we write ByteValue to the
+ output file.
+
+Returns:
+
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddByte (ByteValue, Key);
+}
+VOID
+EfiVfrParser::WriteWord (
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ During VFR parsing we came upon a case where we need to write out a
+ 16-bit value. Queue it up.
+
+Arguments:
+ Value - value to write.
+
+Returns:
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
+}
+VOID
+EfiVfrParser::WriteStringIdWord (
+ UINT16 WordValue
+ )
+{
+ mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
+ mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
+}
+VOID
+EfiVfrParser::FreeGotoReferences ()
+/*++
+
+Routine Description:
+ Called during cleanup to free up the memory we allocated when
+ keeping track of VFR goto statements.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ GOTO_REFERENCE *CurrRef;
+ GOTO_REFERENCE *NextRef;
+ FORM_ID_VALUE *CurrFormId;
+ FORM_ID_VALUE *NextFormId;
+ UINT8 Found;
+ CHAR8 Name[20];
+
+ //
+ // Go through all the "goto" references and make sure there was a
+ // form ID of that value defined.
+ //
+ for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {
+ Found = 0;
+ for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {
+ if (CurrRef->Value == CurrFormId->Value) {
+ Found = 1;
+ break;
+ }
+ }
+ if (!Found) {
+ sprintf (Name, "%d", (UINT32)CurrRef->Value);
+ PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");
+ }
+ }
+ //
+ // Now free up the form id and goto references
+ //
+ CurrFormId = mFormIdValues;
+ while (CurrFormId != NULL) {
+ NextFormId = CurrFormId->Next;
+ free (CurrFormId);
+ CurrFormId = NextFormId;
+ }
+ mFormIdValues = NULL;
+ CurrRef = mGotoReferences;
+ while (CurrRef != NULL) {
+ NextRef = CurrRef->Next;
+ free (CurrRef);
+ CurrRef = NextRef;
+ }
+ mGotoReferences = NULL;
+}
+VOID
+EfiVfrParser::AddGotoReference (
+ UINT32 GotoNumber,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ During VFR parsing we came upon a goto statement. Since we support
+ forward references, save the referenced label and at the end of parsing
+ we'll check that the label was actually defined somewhere.
+
+Arguments:
+ GotoNumber - the label number referenced
+ LineNum - the line number where the reference was made (used for
+ error reporting)
+
+Returns:
+ None
+
+--*/
+{
+ GOTO_REFERENCE *NewRef;
+
+ NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));
+ if (NewRef == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return;
+ }
+ memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));
+ NewRef->Value = (UINT16)GotoNumber;
+ NewRef->RefLineNum = LineNum;
+ NewRef->Next = mGotoReferences;
+ mGotoReferences = NewRef;
+}
+VOID
+EfiVfrParser::AddFormId (
+ INT32 FormIdValue,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This function is called when we parse "form formid = 3" statements.
+ We save the form ID valud so we can verify that duplicates are not
+ defined. Also, these are the targets of goto statements, so when we're
+ done parsing the script we also go through all the goto statements to
+ check that there was a target FormId defined as referenced by each
+ goto statement.
+
+ Note that formid = 0 is invalid.
+
+Arguments:
+ FormIdValue - the parsed value for the Form ID
+ LineNum - line number of the source file we're parsing
+
+Returns:
+ NA
+
+--*/
+{
+ FORM_ID_VALUE *NewFormId;
+ char *FileName;
+ char *FileName2;
+ UINT32 LineNum2;
+ //
+ // Verify that FormId != 0
+ //
+ if (FormIdValue == 0) {
+ FileName = ConvertLineNumber (&LineNum);
+ Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);
+ return;
+ }
+ //
+ // First go through all previously defined form IDs and make sure they have not defined
+ // duplicates.
+ //
+ for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {
+ if ((UINT16)FormIdValue == NewFormId->Value) {
+ FileName = ConvertLineNumber (&LineNum);
+ LineNum2 = NewFormId->LineNum;
+ FileName2 = ConvertLineNumber (&LineNum2);
+ Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);
+ Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);
+ return;
+ }
+ }
+ //
+ // Allocate memory for a new one
+ //
+ NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));
+ if (NewFormId == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return;
+ }
+ memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));
+ NewFormId->LineNum = LineNum;
+ NewFormId->Next = mFormIdValues;
+ NewFormId->Value = (UINT16)FormIdValue;
+ mFormIdValues = NewFormId;
+}
+UINT32
+EfiVfrParser::GetNumber (
+ CHAR8 *NumStr,
+ UINT32 LineNum,
+ UINT32 NumBytes
+ )
+{
+ UINT32 Value;
+
+ if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {
+ AtoX (NumStr + 2, 4, &Value);
+ } else {
+ Value = (UINT32)atoi (NumStr);
+ }
+ //
+ // Check range
+ //
+ if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {
+ PrintErrorMessage (LineNum, NumStr, "value out of range");
+ return 0;
+ }
+ return Value;
+}
+
+>>
+
+} // end grammar class
+
diff --git a/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp b/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp
new file mode 100644
index 0000000000..c66d4dfa79
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp
@@ -0,0 +1,757 @@
+/*++
+
+Copyright (c) 2004 - 2005, 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:
+
+ VfrServices.cpp
+
+Abstract:
+
+ Support routines for the VFR compiler
+
+--*/
+
+#include <stdio.h> // for FILE routines
+#include <stdlib.h> // for malloc() and free()
+
+#include <Base.h>
+#include <UefiBaseTypes.h>
+#include <MultiPhase.h>
+#include "EfiUtilityMsgs.h"
+#include "EfiVfr.h"
+#include "VfrServices.h"
+
+#include <UgaDraw.h>
+#include <Hii.h>
+
+static const char *mSourceFileHeader[] = {
+ "//",
+ "// DO NOT EDIT -- auto-generated file",
+ "//",
+ "// This file is generated by the VFR compiler.",
+ "//",
+ NULL
+};
+
+typedef struct {
+ CHAR8 *Name;
+ INT32 Size;
+} IFR_OPCODE_SIZES;
+
+//
+// Create a table that can be used to do internal checking on the IFR
+// bytes we emit.
+//
+static const IFR_OPCODE_SIZES mOpcodeSizes[] = {
+ { 0, 0 }, // invalid
+ { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },
+ { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) },
+ { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) },
+ { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP
+ { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) },
+ { "EFI_IFR_CHECKBOX", sizeof (EFI_IFR_CHECKBOX) },
+ { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) },
+ { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) },
+ { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) },
+ { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) },
+ { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) },
+ { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) },
+ { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) },
+ { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) },
+ { "EFI_IFR_REF", sizeof (EFI_IFR_REF) },
+ { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) },
+ { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) },
+ { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) },
+ { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) },
+ { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) },
+ { "EFI_IFR_AND", sizeof (EFI_IFR_AND) },
+ { "EFI_IFR_OR", sizeof (EFI_IFR_OR) },
+ { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) },
+ { "EFI_IFR_END_EXPR", sizeof (EFI_IFR_END_EXPR) },
+ { "EFI_IFR_GRAY_OUT", sizeof (EFI_IFR_GRAY_OUT) },
+ { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 },
+ { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 },
+ { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) },
+ { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) },
+ { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) },
+ { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) },
+ { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },
+ { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },
+ { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },
+ { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },
+ { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },
+ { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },
+ { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },
+ { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},
+ { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},
+ { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},
+ { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},
+ { "EFI_IFR_OEM_DEFINED_OP", -2 },
+};
+
+
+VfrOpcodeHandler::VfrOpcodeHandler (
+ )
+/*++
+
+Routine Description:
+ Constructor for the VFR opcode handling class.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ mIfrBytes = NULL;
+ mLastIfrByte = NULL;
+ mBytesWritten = 0;
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ mPrimaryVarStoreId = 0;
+ mSecondaryVarStoreId = 0;
+ mSecondaryVarStoreIdSet = 0;
+ mPrimaryVarStoreIdSet = 0;
+ mDefaultVarStoreId = 0;
+}
+
+VOID
+VfrOpcodeHandler::SetVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a variable is referenced in the
+ VFR. Save the variable store (and set a flag) so that we can later determine
+ if we need to emit a varstore-select or varstore-select-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mPrimaryVarStoreId = VarStoreId;
+ mPrimaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::SetSecondaryVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a secondary variable is
+ referenced in the VFR. Save the variable store (and set a flag) so
+ that we can later determine if we need to emit a varstore-select or
+ varstore-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mSecondaryVarStoreId = VarStoreId;
+ mSecondaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::WriteIfrBytes (
+ )
+/*++
+
+Routine Description:
+ This function is invoked at the end of parsing. Its purpose
+ is to write out all the IFR bytes that were queued up while
+ parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ UINT32 Count;
+ UINT32 LineCount;
+ UINT32 PoundLines;
+ UINT32 ByteCount;
+ CHAR8 Line[MAX_LINE_LEN];
+ CHAR8 *Cptr;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT32 ListFile;
+ EFI_HII_IFR_PACK_HEADER IfrHeader;
+ UINT8 *Ptr;
+ FILE *IfrBinFptr;
+ UINT32 BytesLeftThisOpcode;
+ //
+ // If someone added a new opcode and didn't update our opcode sizes structure, error out.
+ //
+ if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {
+ Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");
+ return;
+ }
+ //
+ // Flush the queue
+ //
+ FlushQueue ();
+ //
+ // If there have been any errors to this point, then skip dumping the IFR
+ // binary data. This way doing an nmake again will try to build it again, and
+ // the build will fail if they did not fix the problem.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the standard file header to the output file
+ //
+ WriteStandardFileHeader (IfrBinFptr);
+ //
+ // Write the structure header
+ //
+ fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);
+ //
+ // Write the header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ if ((Count & 0x03) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", *Ptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ fprintf (IfrBinFptr, "\n // start of IFR data");
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ if ((Count & 0x0F) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ if (Curr->KeyByte != 0) {
+ fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);
+ Count++;
+ Curr = Curr->Next;
+ }
+ fprintf (IfrBinFptr, "\n};\n\n");
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // Write the bytes as binary data if the user specified to do so
+ //
+ if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {
+ //
+ // Use the Ifr output file name with a ".hpk" extension.
+ //
+ for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;
+ (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');
+ Cptr--) {
+ //
+ // do nothing
+ //
+ }
+ if (*Cptr == '.') {
+ strcpy (Cptr, ".hpk");
+ } else {
+ strcat (gOptions.IfrOutputFileName, ".hpk");
+ }
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the structure header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ fwrite (Ptr, 1, 1, IfrBinFptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);
+ Curr = Curr->Next;
+ }
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // If creating a listing file, then open the input and output files
+ //
+ ListFile = 0;
+ if (gOptions.CreateListFile) {
+ //
+ // Open the input VFR file and the output list file
+ //
+ if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");
+ } else {
+ if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ LineCount = 0;
+ ListFile = 1;
+ PoundLines = 0;
+ ByteCount = 0;
+ }
+ }
+ }
+ //
+ // Write the list file
+ //
+ if (ListFile) {
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ //
+ // Print lines until we reach the line of the current opcode
+ //
+ while (LineCount < PoundLines + Curr->LineNum) {
+ if (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ //
+ // We should check for line length exceeded on the fgets(). Otherwise it
+ // throws the listing file output off. Future enhancement perhaps.
+ //
+ fprintf (OutFptr, "%s", Line);
+ if (strncmp (Line, "#line", 5) == 0) {
+ PoundLines++;
+ }
+ }
+ LineCount++;
+ }
+ //
+ // Print all opcodes with line numbers less than where we are now
+ //
+ BytesLeftThisOpcode = 0;
+ while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, ">%08X: ", ByteCount);
+ if (Curr->Next != NULL) {
+ BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;
+ }
+ }
+ fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);
+ ByteCount++;
+ BytesLeftThisOpcode--;
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, "\n");
+ }
+ Curr = Curr->Next;
+ }
+ }
+ //
+ // Dump any remaining lines from the input file
+ //
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ fprintf (OutFptr, "%s", Line);
+ }
+ fclose (InFptr);
+ fclose (OutFptr);
+ }
+ //
+ // Debug code to make sure that each opcode we write out has as many
+ // bytes as the IFR structure requires. If there were errors, then
+ // don't do this step.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ Curr = mIfrBytes;
+ ByteCount = 0;
+ while (Curr != NULL) {
+ //
+ // First byte is the opcode, second byte is the length
+ //
+ if (Curr->Next == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");
+ break;
+ }
+ Count = (UINT32)Curr->Next->OpcodeByte;
+ if (Count == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "opcode with 0 length specified in output at offset 0x%X",
+ ByteCount
+ );
+ break;
+ }
+ //
+ // Check the length
+ //
+ if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32) Curr->OpcodeByte, ByteCount
+ );
+ } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {
+ //
+ // For those cases where the length is variable, the size is negative, and indicates
+ // the miniumum size.
+ //
+ if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "insufficient number of bytes written for %s at offset 0x%X",
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ } else {
+ //
+ // Check for gaps
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32)Curr->OpcodeByte,
+ ByteCount
+ );
+ } else {
+ //
+ // Check size
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",
+ Count,
+ mOpcodeSizes[Curr->OpcodeByte].Size,
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ }
+ }
+ //
+ // Skip to next opcode
+ //
+ while (Count > 0) {
+ ByteCount++;
+ if (Curr == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");
+ break;
+ }
+ Curr = Curr->Next;
+ Count--;
+ }
+ }
+ }
+}
+
+VfrOpcodeHandler::~VfrOpcodeHandler(
+ )
+/*++
+
+Routine Description:
+ Destructor for the VFR opcode handler. Free up memory allocated
+ while parsing the VFR script.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ //
+ // Free up the IFR bytes
+ //
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ Next = Curr->Next;
+ free (Curr);
+ Curr = Next;
+ }
+}
+
+int
+VfrOpcodeHandler::AddOpcodeByte (
+ UINT8 OpcodeByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a new IFR
+ opcode should be emitted.
+
+Arguments:
+ OpcodeByte - the IFR opcode
+ LineNum - the line number from the source file that resulted
+ in the opcode being emitted.
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+
+ FlushQueue();
+ //
+ // Now add this new byte
+ //
+ mQueuedOpcodeByte = OpcodeByte;
+ mQueuedLineNum = LineNum;
+ mQueuedOpcodeByteValid = 1;
+ return 0;
+}
+
+VOID
+VfrOpcodeHandler::AddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when it determines
+ that more raw IFR bytes should be emitted to the output stream.
+ Here we just queue them up into an output buffer.
+
+Arguments:
+ ByteVal - the raw byte to emit to the output IFR stream
+ KeyByte - a value that can be used for debug.
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // Check for buffer overflow
+ //
+ if (mQueuedByteCount > MAX_QUEUE_COUNT) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");
+ } else {
+ mQueuedBytes[mQueuedByteCount] = ByteVal;
+ mQueuedKeyBytes[mQueuedByteCount] = KeyByte;
+ mQueuedByteCount++;
+ }
+}
+
+int
+VfrOpcodeHandler::FlushQueue (
+ )
+/*++
+
+Routine Description:
+ This function is invoked to flush the internal IFR buffer.
+
+Arguments:
+ None
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+ UINT32 EmitNoneOnePair;
+
+ EmitNoneOnePair = 0;
+ //
+ // If the secondary varstore was specified, then we have to emit
+ // a varstore-select-pair opcode, which only applies to the following
+ // statement.
+ //
+ if (mSecondaryVarStoreIdSet) {
+ mSecondaryVarStoreIdSet = 0;
+ //
+ // If primary and secondary are the same as the current default
+ // varstore, then we don't have to do anything.
+ // Note that the varstore-select-pair only applies to the following
+ // opcode.
+ //
+ if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {
+ IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);
+ }
+ } else if (mPrimaryVarStoreIdSet != 0) {
+ mPrimaryVarStoreIdSet = 0;
+ if (mDefaultVarStoreId != mPrimaryVarStoreId) {
+ //
+ // The VFR statement referenced a different variable store
+ // than the last one we reported. Insert a new varstore select
+ // statement.
+ //
+ IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ mDefaultVarStoreId = mPrimaryVarStoreId;
+ }
+ }
+ //
+ // Likely a new opcode is being added. Since each opcode item in the IFR has
+ // a header that specifies the size of the opcode item (which we don't
+ // know until we find the next opcode in the VFR), we queue up bytes
+ // until we know the size. Then we write them out. So flush the queue
+ // now.
+ //
+ if (mQueuedOpcodeByteValid != 0) {
+ //
+ // Add the previous opcode byte, the length byte, and the binary
+ // data.
+ //
+ IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);
+ for (Count = 0; Count < mQueuedByteCount; Count++) {
+ IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);
+ }
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ }
+ return 0;
+}
+
+int
+VfrOpcodeHandler::IAddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This internal function is used to add actual IFR bytes to
+ the output stream. Most other functions queue up the bytes
+ in an internal buffer. Once they come here, there's no
+ going back.
+
+
+Arguments:
+ ByteVal - value to write to output
+ KeyByte - key value tied to the byte -- useful for debug
+ LineNum - line number from source file the byte resulted from
+
+Returns:
+ 0 - if successful
+ 1 - failed due to memory allocation failure
+
+--*/
+{
+ IFR_BYTE *NewByte;
+ NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));
+ if (NewByte == NULL) {
+ return 1;
+ }
+ memset ((char *)NewByte, 0, sizeof (IFR_BYTE));
+ NewByte->OpcodeByte = ByteVal;
+ NewByte->KeyByte = KeyByte;
+ NewByte->LineNum = LineNum;
+ //
+ // Add to the list
+ //
+ if (mIfrBytes == NULL) {
+ mIfrBytes = NewByte;
+ } else {
+ mLastIfrByte->Next = NewByte;
+ }
+ mLastIfrByte = NewByte;
+ mBytesWritten++;
+ return 0;
+}
+
+VOID
+WriteStandardFileHeader (
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+ This function is invoked to emit a standard header to an
+ output text file.
+
+Arguments:
+ OutFptr - file to write the header to
+
+Returns:
+ None
+
+--*/
+{
+ UINT32 TempIndex;
+ for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
+ fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
+ }
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+}
diff --git a/Tools/Source/TianoTools/VfrCompile/VfrServices.h b/Tools/Source/TianoTools/VfrCompile/VfrServices.h
new file mode 100644
index 0000000000..6b8c560d63
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/VfrServices.h
@@ -0,0 +1,227 @@
+/*++
+
+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:
+
+ VfrServices.h
+
+Abstract:
+
+ Prototypes and defines for routines and classes used by the
+ EFI VFR compiler.
+
+--*/
+
+#ifndef _VFR_SERVICES_H_
+#define _VFR_SERVICES_H_
+
+class VfrOpcodeHandler
+{
+public:
+ VfrOpcodeHandler (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ Constructor for the VFR opcode handling class.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ ~VfrOpcodeHandler (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ Destructor for the VFR opcode handler. Free up memory allocated
+ while parsing the VFR script.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ WriteIfrBytes (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ This function is invoked at the end of parsing. Its purpose
+ is to write out all the IFR bytes that were queued up while
+ parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ int
+ AddOpcodeByte (
+ UINT8 OpcodeByte,
+ UINT32 LineNum
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a new IFR
+ opcode should be emitted.
+
+Arguments:
+ OpcodeByte - the IFR opcode
+ LineNum - the line number from the source file that resulted
+ in the opcode being emitted.
+
+Returns:
+ 0 always
+
+--*/
+ ;
+ void
+ AddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when it determines
+ that more raw IFR bytes should be emitted to the output stream.
+ Here we just queue them up into an output buffer.
+
+Arguments:
+ ByteVal - the raw byte to emit to the output IFR stream
+ KeyByte - a value that can be used for debug.
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ SetVarStoreId (
+ UINT16 VarStoreId
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a variable is referenced in the
+ VFR. Save the variable store (and set a flag) so that we can later determine
+ if we need to emit a varstore-select or varstore-select-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ SetSecondaryVarStoreId (
+ UINT16 VarStoreId
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a secondary variable is
+ referenced in the VFR. Save the variable store (and set a flag) so
+ that we can later determine if we need to emit a varstore-select or
+ varstore-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+ ;
+
+/* */
+private:
+ int
+ FlushQueue (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ This function is invoked to flush the internal IFR buffer.
+
+Arguments:
+ None
+
+Returns:
+ 0 always
+
+--*/
+ ;
+ int
+ IAddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte,
+ UINT32 LineNum
+ )
+ /*++
+
+Routine Description:
+ This internal function is used to add actual IFR bytes to
+ the output stream. Most other functions queue up the bytes
+ in an internal buffer. Once they come here, there's no
+ going back.
+
+
+Arguments:
+ ByteVal - value to write to output
+ KeyByte - key value tied to the byte -- useful for debug
+ LineNum - line number from source file the byte resulted from
+
+Returns:
+ 0 - if successful
+ 1 - failed due to memory allocation failure
+
+--*/
+ ;
+
+/* */
+private:
+ IFR_BYTE *mIfrBytes;
+ IFR_BYTE *mLastIfrByte;
+ UINT32 mQueuedByteCount;
+ UINT32 mBytesWritten;
+ UINT32 mQueuedLineNum;
+ UINT8 mQueuedBytes[MAX_QUEUE_COUNT];
+ UINT8 mQueuedKeyBytes[MAX_QUEUE_COUNT];
+ UINT8 mQueuedOpcodeByte;
+ UINT32 mQueuedOpcodeByteValid;
+ UINT16 mPrimaryVarStoreId;
+ UINT8 mPrimaryVarStoreIdSet;
+ UINT16 mSecondaryVarStoreId;
+ UINT8 mSecondaryVarStoreIdSet;
+ UINT16 mDefaultVarStoreId;
+};
+
+#endif // #ifndef _VFR_SERVICES_H_
diff --git a/Tools/Source/TianoTools/VfrCompile/build.gcc b/Tools/Source/TianoTools/VfrCompile/build.gcc
new file mode 100644
index 0000000000..b6641721f4
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/build.gcc
@@ -0,0 +1,10 @@
+../../../bin/antlr -CC -e3 -ck 3 -o . VfrCompile.g
+../../../bin/dlg -C2 -i -CC -o . parser.dlg
+g++ -mno-cygwin -c -I -I. -I../Pccts/h -g -O0 ../Pccts/h/AParser.cpp
+g++ -mno-cygwin -c -I. -I../Pccts/h -g -O0 ../Pccts/h/ATokenBuffer.cpp
+g++ -mno-cygwin -c -I. -I../Pccts/h -g -O0 ../Pccts/h/DLexerBase.cpp
+g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 VfrCompile.cpp
+g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 VfrServices.cpp
+g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 DLGLexer.cpp
+g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 EfiVfrParser.cpp
+g++ -mno-cygwin -o VfrCompile *.o -L../Library-mingw -lCommon
diff --git a/Tools/Source/TianoTools/VfrCompile/build.xml b/Tools/Source/TianoTools/VfrCompile/build.xml
new file mode 100644
index 0000000000..217c4075cc
--- /dev/null
+++ b/Tools/Source/TianoTools/VfrCompile/build.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, 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.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK VfrCompile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="VfrCompile"/>
+ <property name="FileSet" value="*.cpp"/>
+ <property name="FileSetPccts" value="ATokenBuffer.cpp DLexerBase.cpp AParser.cpp"/>
+ <taskdef resource="cpptasks.tasks"/>
+ <typedef resource="cpptasks.types"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property environment="env"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Antlr, Dlg, Tool">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ </target>
+
+ <target name="init">
+ <echo message="The EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ <if>
+ <equals arg1="${GCC}" arg2="cygwin"/>
+ <then>
+ <echo message="Cygwin Family"/>
+ <property name="ToolChain" value="gcc"/>
+ </then>
+ <elseif>
+ <os family="dos"/>
+ <then>
+ <echo message="Windows Family"/>
+ <property name="ToolChain" value="msvc"/>
+ </then>
+ </elseif>
+ <elseif>
+ <os family="unix"/>
+ <then>
+ <echo message="UNIX Family"/>
+ <property name="ToolChain" value="gcc"/>
+ </then>
+ </elseif>
+
+ <else>
+ <echo>
+ Unsupported Operating System
+ Please Contact Intel Corporation
+ </echo>
+ </else>
+ </if>
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <property name="ext_static" value=".lib"/>
+ <property name="ext_dynamic" value=".dll"/>
+ <property name="ext_exe" value=".exe"/>
+ </then>
+ <elseif>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ <then>
+ <property name="ext_static" value=".a"/>
+ <property name="ext_dynamic" value=".so"/>
+ <property name="ext_exe" value=""/>
+ </then>
+ </elseif>
+ </if>
+ <condition property="CheckDepends">
+ <uptodate targetfile="${WORKSPACE}/Tools/bin/VfrCompile${ext_exe}">
+ <srcfiles dir="${WORKSPACE}/Tools/Source/TianoTools/VfrCompile" includes="EfiVfrParser.cpp DLGLexer.cpp VfrCompile.cpp VfrCompile.g VfrServices.cpp parser.dlg"/>
+ </uptodate>
+ </condition>
+ </target>
+
+ <target name="Antlr" depends="init" unless="CheckDepends">
+ <exec dir="${basedir}/${ToolName}" executable="antlr.exe" failonerror="TRUE">
+ <arg line="-CC -e3 -ck 3 -o . VfrCompile.g"/>
+ </exec>
+ </target>
+
+ <target name="Dlg" depends="Antlr" unless="CheckDepends">
+ <exec dir="${basedir}/${ToolName}" executable="dlg.exe" failonerror="TRUE">
+ <arg line="-C2 -i -CC -o . Parser.dlg"/>
+ </exec>
+ </target>
+
+ <target name="Tool" depends="init, Dlg">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ libtool="${haveLibtool}"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <fileset dir="${basedir}/Pccts/h"
+ includes="${FileSetPccts}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${env.WORKSPACE}/Tools/Source/TianoTools/Pccts/h"/>
+ <includepath path="${env.WORKSPACE}/MdePkg/Include"/>
+ <includepath path="${env.WORKSPACE}/MdePkg/Include/Ia32"/>
+ <includepath path="${env.WORKSPACE}/MdePkg/Include/Common"/>
+ <includepath path="${env.WORKSPACE}/MdePkg/Include/Protocol"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+
+ <linkerarg value="${LIB_DIR}/CommonTools.lib"/>
+
+ </cc>
+ </target>
+
+ <target name="clean" depends="init">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall" depends="init">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete dir="${BUILD_DIR}">
+ <fileset dir="${BIN_DIR}" includes="${ToolName}${ext_exe}"/>
+ </delete>
+ </target>
+
+</project>