--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ VfrCompile.g\r
+\r
+Abstract:\r
+\r
+ PCCTS parser and lexer definitions for the EFI VFR forms compiler\r
+ \r
+--*/ \r
+\r
+#header<<\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "EfiVfr.h"\r
+#include "VfrServices.h"\r
+#include EFI_PROTOCOL_DEFINITION (Hii)\r
+\r
+#include <ctype.h>\r
+#include <direct.h>\r
+#include <process.h> // for spawn functions\r
+\r
+>>\r
+\r
+<<\r
+\r
+//\r
+// Base info for DLG-generated scanner\r
+//\r
+#include "DLexerBase.h" \r
+\r
+//\r
+// Include the scanner file generated by DLG\r
+//\r
+#include "DLGLexer.h" \r
+\r
+class DLGLexerVfr : public DLGLexer\r
+{\r
+public:\r
+ DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};\r
+ INT32 errstd (char *Text) \r
+ { \r
+ printf ("unrecognized input '%s'\n", Text); \r
+ }\r
+};\r
+\r
+//\r
+// Base token definitions for ANTLR\r
+//\r
+#include "AToken.h"\r
+\r
+//\r
+// This is how we invoke the C preprocessor on the VFR source file\r
+// to resolve #defines, #includes, etc. To make C source files\r
+// shareable between VFR and drivers, define VFRCOMPILE so that\r
+// #ifdefs can be used in shared .h files.\r
+//\r
+#define PREPROCESSOR_COMMAND "cl.exe "\r
+#define PREPROCESSOR_OPTIONS "/nologo /E /TC /DVFRCOMPILE "\r
+\r
+typedef ANTLRCommonToken ANTLRToken;\r
+\r
+//\r
+// Specify the filename extensions for the files we generate.\r
+//\r
+#define VFR_BINARY_FILENAME_EXTENSION ".c"\r
+#define VFR_LIST_FILENAME_EXTENSION ".lst"\r
+#define VFR_PREPROCESS_FILENAME_EXTENSION ".i"\r
+\r
+static \r
+VOID \r
+Usage ();\r
+\r
+static \r
+STATUS \r
+ProcessArgs (\r
+ int Argc, \r
+ char *Argv[]\r
+ );\r
+\r
+static \r
+VOID \r
+Cleanup ();\r
+\r
+//\r
+// Globals\r
+//\r
+OPTIONS gOptions;\r
+\r
+int \r
+main (\r
+ int argc, \r
+ char **argv\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Application entry point function. Parse command-line arguments, \r
+ invoke the parser, clean up, and return.\r
+\r
+Arguments:\r
+ argc - standard argc passed to main() per C conventions\r
+ argv - standard argv passed to main() per C conventions\r
+\r
+Returns:\r
+ STATUS_SUCCESS - program executed with no errors or warnings\r
+ STATUS_WARNING - program executed with warnings\r
+ STATUS_ERROR - non-recoverable errors encountered while processing\r
+\r
+--*/\r
+{\r
+ FILE *VfrFptr;\r
+ char *Cmd;\r
+ char *Cptr;\r
+ int Len;\r
+ STATUS Status;\r
+ \r
+ //\r
+ // Set our program name for the error printing routines.\r
+ // Then set printing limits.\r
+ //\r
+ SetUtilityName (PROGRAM_NAME);\r
+ SetPrintLimits (20, 20, 30);\r
+ //\r
+ // Process the command-line arguments\r
+ //\r
+ if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {\r
+ Usage ();\r
+ Cleanup();\r
+ return STATUS_ERROR;\r
+ }\r
+ VfrFptr = NULL;\r
+ //\r
+ // Verify the VFR script file exists\r
+ //\r
+ if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");\r
+ Cleanup();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Now close the file and make a system call to run the preprocessor\r
+ // on it.\r
+ //\r
+ fclose (VfrFptr);\r
+ Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10 +\r
+ strlen (PREPROCESSOR_COMMAND) + strlen (gOptions.PreprocessorOutputFileName);\r
+ if (gOptions.CPreprocessorOptions != NULL) {\r
+ Len += strlen (gOptions.CPreprocessorOptions) + 1;\r
+ }\r
+ if (gOptions.IncludePaths != NULL) {\r
+ Len += strlen (gOptions.IncludePaths) + 1;\r
+ }\r
+ Cmd = (char *)malloc (Len);\r
+ if (Cmd == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");\r
+ Cleanup();\r
+ return STATUS_ERROR;\r
+ } \r
+ strcpy (Cmd, PREPROCESSOR_COMMAND PREPROCESSOR_OPTIONS);\r
+ if (gOptions.IncludePaths != NULL) {\r
+ strcat (Cmd, gOptions.IncludePaths);\r
+ strcat (Cmd, " ");\r
+ }\r
+ if (gOptions.CPreprocessorOptions != NULL) {\r
+ strcat (Cmd, gOptions.CPreprocessorOptions);\r
+ strcat (Cmd, " ");\r
+ }\r
+ strcat (Cmd, gOptions.VfrFileName);\r
+ strcat (Cmd, " > ");\r
+ strcat (Cmd, gOptions.PreprocessorOutputFileName);\r
+ Status = system (Cmd);\r
+ if (Status != 0) {\r
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");\r
+ printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);\r
+ Cleanup();\r
+ return STATUS_ERROR;\r
+ }\r
+ free (Cmd);\r
+ //\r
+ // Open the preprocessor output file\r
+ //\r
+ if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file", \r
+ gOptions.PreprocessorOutputFileName);\r
+ Cleanup();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Define input VFR file\r
+ //\r
+ DLGFileInput InputFile (VfrFptr);\r
+ //\r
+ // Define an instance of the scanner \r
+ //\r
+ DLGLexerVfr Scanner (&InputFile);\r
+ //\r
+ // Define token buffer between scanner and parser\r
+ //\r
+ ANTLRTokenBuffer Pipe (&Scanner); \r
+ //\r
+ // Create a token to use as a model\r
+ //\r
+ ANTLRToken Tok; \r
+ //\r
+ // Tell the scanner what type the token is\r
+ //\r
+ Scanner.setToken (&Tok); \r
+ //\r
+ // Create an instance of our parser\r
+ //\r
+ EfiVfrParser Parser (&Pipe); \r
+ //\r
+ // Initialize the parser \r
+ //\r
+ Parser.init ();\r
+ Status = GetUtilityStatus ();\r
+ if (Status != STATUS_SUCCESS) {\r
+ Cleanup();\r
+ return Status;\r
+ } \r
+ //\r
+ // Start the first rule \r
+ //\r
+ Parser.program ();\r
+ //\r
+ // Close the input script file\r
+ //\r
+ fclose (VfrFptr);\r
+ Parser.WriteIfrBytes ();\r
+ //\r
+ // Call cleanup, which does some extra checking of the script\r
+ //\r
+ Parser.Cleanup ();\r
+ Cleanup();\r
+ //\r
+ // If we had an error somewhere, delete our output files so that\r
+ // a subsequent build will rebuild them.\r
+ //\r
+ Status = GetUtilityStatus ();\r
+ if (Status == STATUS_ERROR) {\r
+ remove (gOptions.IfrOutputFileName);\r
+ }\r
+ return Status;\r
+}\r
+static\r
+VOID\r
+Cleanup ()\r
+/*++\r
+\r
+Routine Description:\r
+ Free up memory allocated during parsing.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ //\r
+ // Free up our string we allocated to track the include paths\r
+ //\r
+ if (gOptions.IncludePaths != NULL) {\r
+ free (gOptions.IncludePaths);\r
+ gOptions.IncludePaths = NULL;\r
+ }\r
+ //\r
+ // Free up our string we allocated to track preprocessor options\r
+ //\r
+ if (gOptions.CPreprocessorOptions != NULL) {\r
+ free (gOptions.CPreprocessorOptions);\r
+ gOptions.CPreprocessorOptions = NULL;\r
+ }\r
+} \r
+\r
+static\r
+STATUS\r
+ProcessArgs (\r
+ int Argc, \r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Process the command-line arguments.\r
+\r
+Arguments:\r
+ Argc - standard argc passed to main()\r
+ Argv - standard argv passed to main()\r
+\r
+Returns:\r
+ STATUS_SUCCESS - program should continue (all args ok)\r
+\r
+--*/\r
+{\r
+ char *IncludePaths;\r
+ char *CPreprocessorOptions;\r
+ int Len; \r
+ char CopyStr[MAX_PATH];\r
+ char *Cptr;\r
+\r
+ //\r
+ // Put options in known state.\r
+ //\r
+ memset ((char *)&gOptions, 0, sizeof (OPTIONS));\r
+ //\r
+ // Go through all the arguments that start with '-'\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+ while ((Argc > 0) && (Argv[0][0] == '-')) {\r
+ //\r
+ // -? or -h help option -- return an error for printing usage\r
+ //\r
+ if ((_stricmp (Argv[0], "-?") == 0) || (_stricmp (Argv[0], "-h") == 0)) {\r
+ return STATUS_ERROR;\r
+ break;\r
+ //\r
+ // -l to create a listing output file\r
+ //\r
+ } else if (_stricmp (Argv[0], "-l") == 0) {\r
+ gOptions.CreateListFile = 1;\r
+ //\r
+ // -I include_path option for finding include files. We'll pass this\r
+ // to the preprocessor. Turn them all into a single include string.\r
+ //\r
+ } else if (_stricmp (Argv[0], "-i") == 0) {\r
+ if ((Argc < 2) || (Argv[1][0] == '-')) {\r
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument");\r
+ return STATUS_ERROR;\r
+ }\r
+ Argc--;\r
+ Argv++;\r
+ Len = strlen (" -I ");\r
+ Len += strlen (Argv[0]) + 2;\r
+ if (gOptions.IncludePaths != NULL) {\r
+ Len += strlen (gOptions.IncludePaths);\r
+ }\r
+ IncludePaths = (INT8 *)malloc (Len);\r
+ if (IncludePaths == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");\r
+ return STATUS_ERROR;\r
+ }\r
+ IncludePaths[0] = 0;\r
+ if (gOptions.IncludePaths != NULL) {\r
+ strcpy (IncludePaths, gOptions.IncludePaths);\r
+ free (gOptions.IncludePaths);\r
+ }\r
+ strcat (IncludePaths, " -I ");\r
+ strcat (IncludePaths, Argv[0]);\r
+ gOptions.IncludePaths = IncludePaths;\r
+ //\r
+ // -od OutputDirectory to define a common directory for output files\r
+ //\r
+ } else if (_stricmp (Argv[0], "-od") == 0) {\r
+ if ((Argc < 2) || (Argv[1][0] == '-')) {\r
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");\r
+ return STATUS_ERROR;\r
+ }\r
+ Argc--;\r
+ Argv++;\r
+ strcpy (gOptions.OutputDirectory, Argv[0]);\r
+ } else if (_stricmp (Argv[0], "-ibin") == 0) {\r
+ gOptions.CreateIfrBinFile = 1;\r
+ } else if (_stricmp (Argv[0], "-nostrings") == 0) {\r
+ // deprecated option\r
+ //\r
+ // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.\r
+ // Turn them all into a single string.\r
+ //\r
+ } else if (_stricmp (Argv[0], "-ppflag") == 0) {\r
+ if (Argc < 2) {\r
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");\r
+ return STATUS_ERROR;\r
+ }\r
+ Argc--;\r
+ Argv++;\r
+ Len = strlen (Argv[0]) + 2;\r
+ if (gOptions.CPreprocessorOptions != NULL) {\r
+ Len += strlen (gOptions.CPreprocessorOptions);\r
+ }\r
+ CPreprocessorOptions = (INT8 *)malloc (Len);\r
+ if (CPreprocessorOptions == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");\r
+ return STATUS_ERROR;\r
+ }\r
+ CPreprocessorOptions[0] = 0;\r
+ if (gOptions.CPreprocessorOptions != NULL) {\r
+ strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);\r
+ free (gOptions.CPreprocessorOptions);\r
+ }\r
+ strcat (CPreprocessorOptions, " ");\r
+ strcat (CPreprocessorOptions, Argv[0]);\r
+ gOptions.CPreprocessorOptions = CPreprocessorOptions;\r
+ } else {\r
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");\r
+ return STATUS_ERROR;\r
+ }\r
+ Argc--;\r
+ Argv++;\r
+ }\r
+ //\r
+ // Must specify at least the vfr file name\r
+ //\r
+ if (Argc > 1) {\r
+ Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");\r
+ return STATUS_ERROR;\r
+ } else if (Argc < 1) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");\r
+ return STATUS_ERROR;\r
+ }\r
+ strcpy (gOptions.VfrFileName, Argv[0]);\r
+ \r
+ strcpy (CopyStr, gOptions.VfrFileName);\r
+ Cptr = CopyStr + strlen (CopyStr) - 1;\r
+ for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':'); Cptr--);\r
+ if (Cptr == CopyStr) {\r
+ strcpy (gOptions.VfrBaseFileName, Cptr);\r
+ } else {\r
+ strcpy (gOptions.VfrBaseFileName, Cptr+1);\r
+ }\r
+ //\r
+ // Terminate the vfr file basename at the extension\r
+ //\r
+ for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {\r
+ }\r
+ *Cptr = 0; \r
+ //\r
+ // If they defined an output directory, prepend all output files\r
+ // with the working directory. Output files of interest:\r
+ // VfrListFileName -- list file\r
+ // IfrOutputFileName -- IFR bytes \r
+ // StringOutputFileName -- string bytes\r
+ // StringListFileName -- not used\r
+ // StringDefineFileName -- #defines of string identifiers\r
+ //\r
+ // We have two cases:\r
+ // 1. Output directory (-od) not specified, in which case output files\r
+ // go to the current working directory.\r
+ // 2. Output directory specified, in which case the output files\r
+ // go directly to the specified directory.\r
+ //\r
+ if (gOptions.OutputDirectory[0] == 0) {\r
+ CopyStr[0] = 0;\r
+ _getcwd (CopyStr, sizeof (CopyStr));\r
+ strcpy (gOptions.OutputDirectory, CopyStr);\r
+ }\r
+ //\r
+ // Make sure output directory has a trailing backslash\r
+ //\r
+ if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\') {\r
+ strcat (gOptions.OutputDirectory, "\\");\r
+ }\r
+ //\r
+ // Create the base output file name as: path\base, copy it to all the output\r
+ // filenames, and then add the appropriate extension to each.\r
+ //\r
+ strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);\r
+ strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);\r
+ strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);\r
+ strcpy (gOptions.PreprocessorOutputFileName, gOptions.VfrListFileName);\r
+ strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);\r
+ strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);\r
+ strcat (gOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);\r
+ \r
+ //\r
+ // We set a default list file name, so if they do not\r
+ // want a list file, null out the name now.\r
+ //\r
+ if (gOptions.CreateListFile == 0) {\r
+ gOptions.VfrListFileName[0] = 0;\r
+ }\r
+ return STATUS_SUCCESS;\r
+}\r
+static \r
+VOID \r
+Usage ()\r
+/*++\r
+\r
+Routine Description:\r
+ Print utility usage instructions\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ int Index;\r
+ const char *Help[] = {\r
+ " ", \r
+ "VfrCompile version " VFR_COMPILER_VERSION,\r
+ " ",\r
+ " Usage: VfrCompile {options} [VfrFile]",\r
+ " ",\r
+ " where options include:",\r
+ " -? or -h prints this help",\r
+ " -l create an output IFR listing file",\r
+ " -i IncPath add IncPath to the search path for VFR included files",\r
+ " -od OutputDir deposit all output files to directory OutputDir (default=cwd)",\r
+ " -ibin create an IFR HII pack file",\r
+ " where parameters include:",\r
+ " VfrFile name of the input VFR script file",\r
+ " ",\r
+ NULL\r
+ };\r
+ for (Index = 0; Help[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Help[Index]);\r
+ }\r
+}\r
+ \r
+>>\r
+\r
+\r
+#lexaction\r
+<<\r
+\r
+#include "EfiVfr.h"\r
+\r
+PARSER_LINE_DEFINITION *gLineDefinition = NULL;\r
+PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;\r
+\r
+VOID\r
+AddFileLine (\r
+ char *TokenString,\r
+ UINT32 TokenLine\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ During the lexer phase, if we encounter a #line statement output by\r
+ the preprocessor, this function gets called. We'll save off the info \r
+ for error reporting purposes. The preprocessor line information has the\r
+ form:\r
+ \r
+ #line 3 "FileName.c" \r
+\r
+Arguments:\r
+ TokenString - the parsed string as shown above\r
+ TokenLine - the line number in the preprocessed output file \r
+ \r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ PARSER_LINE_DEFINITION *LineDef;\r
+ INT8 *Cptr;\r
+ \r
+ //\r
+ // Allocate a structure in which we can keep track of this line information.\r
+ //\r
+ LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));\r
+ memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));\r
+ LineDef->TokenLineNum = TokenLine;\r
+ LineDef->HashLineNum = atoi (TokenString + 6);\r
+ //\r
+ // Find the quotes in the filename, then allocate space in the line\r
+ // def structure for a copy of the filename. Finally, copy it without\r
+ // quotes to the line def.\r
+ //\r
+ for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);\r
+ if (*Cptr == '"') {\r
+ LineDef->FileName = (INT8 *)malloc (strlen (Cptr));\r
+ Cptr++;\r
+ strcpy (LineDef->FileName, Cptr);\r
+ for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);\r
+ *Cptr = 0; \r
+ //\r
+ // Now add this new one to the list\r
+ //\r
+ if (gLineDefinition == NULL) {\r
+ gLineDefinition = LineDef;\r
+ } else {\r
+ gLastLineDefinition->Next = LineDef;\r
+ }\r
+ gLastLineDefinition = LineDef;\r
+ } else {\r
+ Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);\r
+ free (LineDef);\r
+ return;\r
+ }\r
+}\r
+char *\r
+ConvertLineNumber (\r
+ UINT32 *LineNum\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Given the line number in the preprocessor-output file, use the line number\r
+ information we've saved to determine the source file name and line number\r
+ where the code originally came from. This is required for error reporting.\r
+\r
+Arguments:\r
+ LineNum - the line number in the preprocessor-output file.\r
+\r
+Returns:\r
+ Returns a pointer to the source file name. Also returns the line number \r
+ in the provided LineNum argument\r
+\r
+--*/\r
+{\r
+ PARSER_LINE_DEFINITION *LineDef;\r
+ //\r
+ // Step through our linked list of #line information we saved off. \r
+ // For each one, look at its line number, and the line number of the\r
+ // next record, and see if the passed-in line number is in the range.\r
+ // If it is, then convert the line number to the appropriate line number\r
+ // of the original source file.\r
+ //\r
+ for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {\r
+ //\r
+ // The given LineNum is the line number from the .i file.\r
+ // Find a line definition whose range includes this line number,\r
+ // convert the line number, and return the filename.\r
+ //\r
+ if (LineDef->TokenLineNum <= *LineNum) {\r
+ if (LineDef->Next != NULL) {\r
+ if (LineDef->Next->TokenLineNum > *LineNum) {\r
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;\r
+ return LineDef->FileName;\r
+ }\r
+ } else {\r
+ //\r
+ // Last one in the list of line definitions, so has to be right\r
+ //\r
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;\r
+ return LineDef->FileName;\r
+ }\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
+>>\r
+\r
+//\r
+// Define a lexical class for parsing quoted strings. Basically\r
+// starts with a double quote, and ends with a double quote that\r
+// is not preceeded with a backslash.\r
+//\r
+#lexclass QUOTED_STRING\r
+#token TheString "~[\"]*\"" << mode (START); >> \r
+\r
+//\r
+// Define a lexical class for parsing "#pragma pack" statements. \r
+// We do this just for convenience (since we skip them here) so\r
+// that users can include some minimal .h files.\r
+//\r
+#lexclass PRAGMA_PACK\r
+#token "pack" << skip (); >>\r
+#token "[\ \t]" << skip (); >> \r
+#token "\(" << skip (); >>\r
+#token "[0-9]*" << skip (); >>\r
+#token "\)" << skip (); mode (START); >>\r
+\r
+//\r
+// Define a lexclass for skipping over C++ style comments\r
+//\r
+#lexclass CPP_COMMENT\r
+#token "~[\n]*" << skip (); >>\r
+#token "\n" << skip (); mode (START); newline (); >>\r
+\r
+//\r
+// Standard lexclass is START\r
+//\r
+#lexclass START\r
+\r
+//\r
+// Find start of C++ style comments\r
+//\r
+#token "//" << skip (); mode (CPP_COMMENT); >>\r
+\r
+//\r
+// Skip whitespace\r
+//\r
+#token "[\ \t]" << skip (); >> \r
+\r
+//\r
+// Skip over newlines, but count them\r
+//\r
+#token "\n" << skip (); newline (); >>\r
+\r
+//\r
+// Skip pragma pack statements\r
+//\r
+#token "\#pragma" << skip (); mode(PRAGMA_PACK); >>\r
+\r
+//\r
+// Skip over 'extern' in any included .H file\r
+//\r
+#token "extern" << skip (); >>\r
+\r
+//\r
+// Tokens for the different keywords. Syntax is:\r
+// TokenName("ErrorMessageText") "TokenString"\r
+// where:\r
+// TokenName is the token name (must be capitalized) that is used in the rules\r
+// ErrorMessageText is the string the compiler emits when it detects a syntax error\r
+// TokenString is the actual matching string used in the user script\r
+//\r
+#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>\r
+#token FormSet("formset") "formset"\r
+#token EndFormSet("endformset") "endformset"\r
+#token Title("title") "title"\r
+#token FormId("formid") "formid"\r
+#token OneOf("oneof") "oneof"\r
+#token Prompt("prompt") "prompt"\r
+#token OrderedList("orderedlist") "orderedlist"\r
+#token EndList("endlist") "endlist"\r
+#token EndForm("endform") "endform"\r
+#token EndOneOf("endoneof") "endoneof"\r
+#token Form("form") "form"\r
+#token Subtitle("subtitle") "subtitle"\r
+#token Help("help") "help"\r
+#token VarId("varid") "varid"\r
+#token Text("text") "text"\r
+#token Option("option") "option"\r
+#token Value("value") "value"\r
+#token Flags("flags") "flags"\r
+#token Date("date") "date"\r
+#token EndDate("enddate") "enddate"\r
+#token Year("year") "year"\r
+#token Month("month") "month"\r
+#token Day("day") "day"\r
+#token Time("time") "time"\r
+#token EndTime("endtime") "endtime"\r
+#token Hour("hour") "hour"\r
+#token Minute("minute") "minute"\r
+#token Second("second") "second"\r
+#token AND("AND") "AND"\r
+#token OR("OR") "OR"\r
+#token GrayOutIf("grayoutif") "grayoutif"\r
+#token NOT("NOT") "NOT"\r
+#token Label("label") "label"\r
+#token Timeout("timeout") "timeout"\r
+#token Inventory("inventory") "inventory"\r
+#token StringToken("STRING_TOKEN") "STRING_TOKEN"\r
+#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP"\r
+#token Struct("struct") "struct"\r
+#token Uint64("UINT64") "UINT64"\r
+#token Uint32("UINT32") "UINT32"\r
+#token Uint16("UINT16") "UINT16"\r
+#token Char16("CHAR16") "CHAR16"\r
+#token Uint8("UINT8") "UINT8"\r
+#token Guid("guid") "guid"\r
+#token CheckBox("checkbox") "checkbox"\r
+#token EndCheckBox("endcheckbox") "endcheckbox"\r
+#token Numeric("numeric") "numeric"\r
+#token EndNumeric("endnumeric") "endnumeric" \r
+#token Minimum("minimum") "minimum" \r
+#token Maximum("maximum") "maximum" \r
+#token Step("step") "step" \r
+#token Default("default") "default" \r
+#token Password("password") "password" \r
+#token EndPassword("endpassword") "endpassword" \r
+#token String("string") "string" \r
+#token EndString("endstring") "endstring" \r
+#token MinSize("minsize") "minsize" \r
+#token MaxSize("maxsize") "maxsize" \r
+#token Encoding("encoding") "encoding"\r
+#token SuppressIf("suppressif") "suppressif"\r
+#token Hidden("hidden") "hidden"\r
+#token Goto("goto") "goto"\r
+#token InconsistentIf "inconsistentif"\r
+#token EndIf("endif") "endif"\r
+#token IdEqId("ideqid") "ideqid"\r
+#token IdEqVal("ideqval") "ideqval"\r
+#token VarEqVal("vareqval") "vareqval"\r
+#token Var("var") "var"\r
+#token IdEqValList("ideqvallist") "ideqvallist"\r
+#token Length("length") "length"\r
+#token Values("values") "values"\r
+#token Key("key") "key"\r
+#token DefaultFlag("DEFAULT") "DEFAULT"\r
+#token ManufacturingFlag("MANUFACTURING") "MANUFACTURING"\r
+#token InteractiveFlag("INTERACTIVE") "INTERACTIVE"\r
+#token NVAccessFlag("NV_ACCESS") "NV_ACCESS"\r
+#token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED"\r
+#token LateCheckFlag("LATE_CHECK") "LATE_CHECK"\r
+#token Class("class") "class"\r
+#token Subclass("subclass") "subclass"\r
+#token TypeDef("typedef") "typedef"\r
+#token Restore("restore") "restore"\r
+#token Save("save") "save"\r
+#token Defaults("defaults") "defaults"\r
+#token Banner("banner") "banner"\r
+#token Align("align") "align"\r
+#token Left("left") "left"\r
+#token Right("right") "right"\r
+#token Center("center") "center"\r
+#token Line("line") "line"\r
+#token VarStore("varstore") "varstore"\r
+#token Name("name") "name"\r
+#token Oem("oem") "oem"\r
+#token True("TRUE") "TRUE"\r
+#token False("FALSE") "FALSE"\r
+#token GreaterThan(">") ">"\r
+#token GreaterEqual(">=") ">="\r
+#token LessThan("<") "<"\r
+#token LessEqual("<=") "<="\r
+\r
+//\r
+// Define the class and subclass tokens\r
+//\r
+#token ClassNonDevice("NONDEVICE") "NON_DEVICE"\r
+#token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE"\r
+#token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE"\r
+#token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE"\r
+#token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE"\r
+#token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE"\r
+#token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE"\r
+\r
+#token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION"\r
+#token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION"\r
+#token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE"\r
+#token SubclassSingleUse("SINGLE_USE") "SINGLE_USE"\r
+\r
+#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters\r
+#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*"\r
+#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+"\r
+#token OpenBrace("{") "\{"\r
+#token CloseBrace("}") "\}"\r
+#token OpenParen("(") "\("\r
+#token CloseParen(")") "\)"\r
+#token OpenBracket("[") "\["\r
+#token CloseBracket("]") "\]"\r
+\r
+//\r
+// Define all other invalid characters so that they get through the lexical phase\r
+// and we can catch them during the parse phase. We get much better error\r
+// messages then. \r
+//\r
+#token InvalidCharacters("invalid characters") "~[;:=,\.\|]" \r
+\r
+//\r
+// This is the overall definition of a VFR form definition script.\r
+//\r
+program :\r
+ ( dataStructDefinition )*\r
+ formSetStatement \r
+ ( vfrStatementVarStore )*\r
+ ( formDefinition )*\r
+ EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>\r
+ "@" // end of file\r
+ ;\r
+ \r
+formSetStatement :\r
+ FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>\r
+ Guid "=" \r
+ OpenBrace \r
+ G1:Number ","\r
+ G2:Number ","\r
+ G3:Number ","\r
+ G4:Number ","\r
+ G5:Number ","\r
+ G6:Number ","\r
+ G7:Number ","\r
+ G8:Number ","\r
+ G9:Number ","\r
+ G10:Number ","\r
+ G11:Number \r
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),\r
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),\r
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()\r
+ );\r
+ >>\r
+ ","\r
+ Title "=" getStringId ","\r
+ Help "=" getStringId ","\r
+ //\r
+ // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)\r
+ //\r
+ << WriteDWord (0, 0); WriteDWord (0, 0); >>\r
+ Class "=" CVAL:classDefinition "," << WriteClass (); >>\r
+ Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >>\r
+ << WriteWord (mNvDataStructSize); >>\r
+ ; \r
+\r
+//\r
+// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C\r
+//\r
+classDefinition :\r
+ validClassNames ( "\|" validClassNames )*\r
+ ;\r
+ \r
+validClassNames :\r
+ CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>\r
+ | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>\r
+ | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>\r
+ | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>\r
+ | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>\r
+ | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>\r
+ | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>\r
+ | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>\r
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>\r
+\r
+//\r
+// A form can only be of one subclass type.\r
+//\r
+subclassDefinition :\r
+ SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>\r
+ | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>\r
+ | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>\r
+ | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>\r
+ | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>\r
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>\r
+\r
+//\r
+// Parse a C type data structure for storing VFR setup data. Allow:\r
+// typedef struct _XXX_ {\r
+// (fields)\r
+// } MY_NV_DATA;\r
+//\r
+dataStructDefinition :\r
+ << int IsNonNV = 0; >>\r
+ { TypeDef } \r
+ S:Struct \r
+ (\r
+ NonNvDataMap << IsNonNV = 1; >>\r
+ |\r
+ { StringIdentifier }\r
+ ) << StartStructDefinition (IsNonNV, S->getLine()); >>\r
+ OpenBrace \r
+ dataStructFields \r
+ CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >>\r
+ ";"\r
+ ;\r
+\r
+dataStructFields :\r
+ ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// UINT64 Name[4];\r
+// UINT64 Name;\r
+//\r
+// Used while parsing the NV data map structures.\r
+//\r
+dataStructField64 :\r
+ << int ArrayLength = 1; char IsArray = 0; >>\r
+ "UINT64" \r
+ NAME:StringIdentifier \r
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) \r
+ << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// UINT32 Name[4];\r
+// UINT32 Name;\r
+//\r
+// Used while parsing the NV data map structures.\r
+//\r
+dataStructField32 :\r
+ << int ArrayLength = 1; char IsArray = 0; >>\r
+ "UINT32" \r
+ NAME:StringIdentifier \r
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) \r
+ << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// UINT16 Name[4];\r
+// UINT16 Name;\r
+//\r
+// Used while parsing the NV data map structures.\r
+//\r
+dataStructField16 :\r
+ << int ArrayLength = 1; char IsArray = 0; >>\r
+ ( "UINT16" | "CHAR16" )\r
+ NAME:StringIdentifier \r
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) \r
+ << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// UINT8 Name[4];\r
+// UINT8 Name;\r
+//\r
+// Used while parsing the NV data map structures.\r
+//\r
+dataStructField8 :\r
+ << int ArrayLength = 1; char IsArray = 0; >>\r
+ "UINT8" \r
+ NAME:StringIdentifier \r
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) \r
+ << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// form formid = 1,\r
+// title = STRING_TOKEN(STR_FORM_TITLE);\r
+// -- form statements --\r
+// endform;\r
+//\r
+// The Form ID cannot be 0\r
+//\r
+formDefinition :\r
+ FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >> \r
+ "=" \r
+ VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>\r
+ ","\r
+ Title "=" getStringId ";" // writes string identifier\r
+ ( vfrStatements )*\r
+ ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>\r
+ ;\r
+\r
+//\r
+// VFR statements in a formset\r
+//\r
+vfrStatements :\r
+ vfrStatementSubTitle | \r
+ vfrStatementOneOf |\r
+ vfrStatementTextText |\r
+ vfrStatementCheckBox |\r
+ vfrStatementNumeric |\r
+ vfrStatementDate |\r
+ vfrStatementTime |\r
+ vfrStatementPassword |\r
+ vfrStatementString |\r
+ vfrStatementSuppressIf |\r
+ vfrStatementHidden |\r
+ vfrStatementGoto | \r
+ vfrStatementGrayOutIf |\r
+ vfrStatementInconsistentIf |\r
+ vfrStatementLabel |\r
+ vfrStatementBanner |\r
+ vfrStatementInventory |\r
+ vfrStatementOrderedList |\r
+ vfrStatementOem |\r
+ vfrStatementSaveRestoreDefaults\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// label 100;\r
+//\r
+vfrStatementLabel :\r
+ OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>\r
+ VAL:Number << \r
+ WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); \r
+ AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());\r
+ >>\r
+ ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// oem 0x12, 0x34, 0x56;\r
+//\r
+vfrStatementOem :\r
+ OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>\r
+ ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )\r
+ ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*\r
+ ";"\r
+ ;\r
+ \r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// inconsistentif NOT .... AND NOT .... OR ... endif;\r
+//\r
+vfrStatementInconsistentIf : \r
+ << ResetFlags (); >>\r
+ IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>\r
+ Prompt "=" getStringId ","\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," \r
+ }\r
+ << WriteFlags (); >> // write the flags field\r
+ vfrBooleanExpression\r
+ EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+// \r
+// PARSE:\r
+// TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR \r
+// ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND\r
+// (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR\r
+// vareqval var(VAR_EQ_TEST_NAME) == 0x1)\r
+//\r
+// For supporting complex express, divide the vfrBooleanExpression to two parts\r
+// so that pred-LL(k) parser can parse incrementally.\r
+//\r
+vfrBooleanExpression :\r
+ leftPartVfrBooleanExp { rightPartVfrBooleanExp }\r
+ ;\r
+ \r
+leftPartVfrBooleanExp :\r
+ OpenParen vfrBooleanExpression CloseParen |\r
+ (ideqval | ideqid | ideqvallist | vareqval | truefalse) |\r
+ NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>\r
+ ;\r
+\r
+rightPartVfrBooleanExp :\r
+ AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> |\r
+ OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// TRUE\r
+//\r
+truefalse :\r
+ TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |\r
+ FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};\r
+//\r
+vfrStatementVarStore : \r
+ OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>\r
+ STRUCT_NAME:StringIdentifier ","\r
+ Key "=" KNUM:Number ","\r
+ Name "=" VAR_NAME:StringIdentifier "," \r
+ Guid "=" \r
+ OpenBrace \r
+ G1:Number ","\r
+ G2:Number ","\r
+ G3:Number ","\r
+ G4:Number ","\r
+ G5:Number ","\r
+ G6:Number ","\r
+ G7:Number ","\r
+ G8:Number ","\r
+ G9:Number ","\r
+ G10:Number ","\r
+ G11:Number \r
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),\r
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),\r
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()\r
+ );\r
+ WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2)); \r
+ AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());\r
+ >>\r
+ \r
+ ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE: \r
+// vareqval var(0x100) == 0x20\r
+//\r
+vareqval : \r
+ OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>\r
+ Var OpenParen \r
+ VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>\r
+ CloseParen\r
+ compareNumber\r
+ ;\r
+\r
+ideqval : \r
+ OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>\r
+ vfrStructFieldName[0]\r
+ compareNumber\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// ideqid MyNVData3.Field16A == MyNVData3.Field16B\r
+//\r
+// NOTE: Before processing the second variable store in the ideqid statement, set a global flag\r
+// so that when we parse the second variable we set the secondary variable store id.\r
+//\r
+ideqid : \r
+ OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >>\r
+ vfrStructFieldName[0]\r
+ compareVfrStructFieldNameNL0\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// compareNumber is the combination of compare operation and Number\r
+//\r
+compareNumber :\r
+ (\r
+ "=="\r
+ VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>\r
+ ) |\r
+ (\r
+ GTOPID:GreaterThan\r
+ VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));\r
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>\r
+ ) |\r
+ (\r
+ GEOPID:GreaterEqual\r
+ VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));\r
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>\r
+ ) |\r
+ (\r
+ LTOPID:LessThan\r
+ VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));\r
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);\r
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>\r
+ ) |\r
+ (\r
+ LEOPID:LessEqual\r
+ VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));\r
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);\r
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>\r
+ )\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0]\r
+//\r
+compareVfrStructFieldNameNL0 :\r
+ (\r
+ "==" << mIdEqIdStmt = 1; >>\r
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >>\r
+ ) |\r
+ (\r
+ GTOPID:GreaterThan << mIdEqIdStmt = 1; >>\r
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;\r
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>\r
+ ) |\r
+ (\r
+ GEOPID:GreaterEqual << mIdEqIdStmt = 1; >>\r
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;\r
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>\r
+ ) |\r
+ (\r
+ LTOPID:LessThan << mIdEqIdStmt = 1; >>\r
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;\r
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);\r
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>\r
+ ) |\r
+ (\r
+ LEOPID:LessEqual << mIdEqIdStmt = 1; >>\r
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;\r
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);\r
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>\r
+ )\r
+ ;\r
+ \r
+\r
+ideqvallist : \r
+ OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>\r
+ vfrStructFieldName[0] \r
+ "=="\r
+ ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +\r
+ << FlushQueueIdEqValList(); >>\r
+ ;\r
+ \r
+vfrStatementGoto : \r
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>\r
+ IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>\r
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); \r
+ AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());\r
+ >>\r
+ KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >>\r
+ Help "=" getStringId\r
+ { \r
+ "," \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>\r
+ }\r
+ {\r
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ ";"\r
+ ;\r
+ \r
+vfrStatementHidden : \r
+ IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>\r
+ Value "="\r
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>\r
+ Key "="\r
+ KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>\r
+ ";"\r
+ ; \r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// suppressif <boolean_expression> { grayoutif } <statements>+ endif;\r
+// Note:\r
+// You can have: suppressif:grayoutif:statements:endif\r
+// suppressif:grayoutif:endif -- serves no purpose\r
+// suppressif:statements:endif\r
+// suppressif:endif -- serves no purpose\r
+//\r
+vfrStatementSuppressIf : \r
+ << ResetFlags (); >>\r
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","\r
+ }\r
+ << WriteFlags (); >> // write the flags field \r
+ vfrBooleanExpression\r
+ ";"\r
+ { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+\r
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>\r
+ ;\r
+\r
+//\r
+// This is the form for a grayoutif nested in a suppressif statement\r
+//\r
+suppressIfGrayOutIf :\r
+ << ResetFlags (); >>\r
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," \r
+ }\r
+ << WriteFlags (); >> // write the flags field\r
+ vfrBooleanExpression\r
+ ";"\r
+ ; \r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// grayoutif { flags = n, } <boolean_expression> endif;\r
+// Note:\r
+// You can have: grayoutif:suppressif:statements:endif\r
+// grayoutif:statements:endif\r
+//\r
+//\r
+vfrStatementGrayOutIf :\r
+ << ResetFlags (); >>\r
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," \r
+ }\r
+ << WriteFlags (); >> // write the flags field\r
+ vfrBooleanExpression\r
+ ";"\r
+ { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+ \r
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>\r
+ ;\r
+\r
+//\r
+// This is the format for a suppressif nested in a grayoutif\r
+//\r
+grayoutIfSuppressIf : \r
+ << ResetFlags (); >>\r
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","\r
+ }\r
+ << WriteFlags (); >> // write the flags field\r
+ vfrBooleanExpression\r
+ ";"\r
+ ;\r
+\r
+//\r
+// These are the VFR statements that are valid inside a suppressif or grayoutif statement.\r
+//\r
+suppressIfAndGrayoutIfSubstatements :\r
+ vfrStatementOneOf |\r
+ vfrStatementTextText |\r
+ vfrStatementCheckBox |\r
+ vfrStatementNumeric |\r
+ vfrStatementDate |\r
+ vfrStatementTime |\r
+ vfrStatementPassword |\r
+ vfrStatementString |\r
+ vfrStatementHidden |\r
+ vfrStatementGoto | \r
+ vfrStatementLabel |\r
+ vfrStatementInventory |\r
+ vfrStatementOrderedList |\r
+ vfrStatementSaveRestoreDefaults\r
+ ; \r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// password varid = MyNvData.Password,\r
+// prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),\r
+// help = STRING_TOKEN(STR_PASSWORD_HELP),\r
+// minsize = 6,\r
+// maxsize = 20,\r
+// encoding = 1,\r
+// endpassword; \r
+ \r
+vfrStatementPassword : \r
+ << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>\r
+ IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>\r
+ VarId "=" vfrStructFieldNameArray[0] ","\r
+ Prompt "=" getStringId ","\r
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>\r
+ }\r
+ {\r
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>\r
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>\r
+ Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>\r
+ EndPassword ";" \r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// string varid = MyNv.String,\r
+// prompt = STRING_TOKEN(STR_STRING_PROMPT),\r
+// help = STRING_TOKEN(STR_STRING_HELP),\r
+// flags = INTERACTIVE,\r
+// key = 0x1234,\r
+// minsize = 6,\r
+// maxsize = 0x14,\r
+// endstring; \r
+//\r
+// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error\r
+// reporting we save the line number of the "help" keyword.\r
+//\r
+vfrStatementString : \r
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>\r
+ IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>\r
+ VarId "=" vfrStructFieldNameArray[0] ","\r
+ Prompt "=" getStringId ","\r
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>\r
+ { \r
+ FF:Flags "=" \r
+ flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>\r
+ "," \r
+ }\r
+ {\r
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>\r
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>\r
+ EndString ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// numeric varid = MyIfrNVData.HowOldAreYouInYears, \r
+// prompt = STRING_TOKEN(STR_NUMERIC_PROMPT),\r
+// help = STRING_TOKEN(STR_NUMERIC_HELP),\r
+// flags = INTERACTIVE, // flags is optional\r
+// key = 0x1234, // key is optional if (flags & INTERACTIVE = 0)\r
+// minimum = 0x0,\r
+// maximum = 0xf0,\r
+// step = 1, // step is option, and step=1 if not specified\r
+// default = 0; // default is optional, and default=minimum if not specified\r
+// endnumeric;\r
+//\r
+// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.\r
+// That check is done in WriteFlagsKey() function.\r
+//\r
+vfrStatementNumeric : \r
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>\r
+ IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>\r
+ VarId "=" vfrStructFieldName[2] ","\r
+ Prompt "=" getStringId ","\r
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >>\r
+ }\r
+ {\r
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ minMaxStepDefault \r
+ EndNumeric ";" << WriteMinMaxStepDefault (); >>\r
+ ;\r
+\r
+//\r
+// Parse minimum/maximum/step/default statements. Special cases:\r
+// - if step not specified, then the value is 1\r
+// - if default not specified, then the value is the min value specified\r
+// - if max < min, print a warning and swap the values (changes default too)\r
+//\r
+minMaxStepDefault :\r
+ << InitMinMaxStepDefault (); >>\r
+ Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >>\r
+ Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >>\r
+ { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }\r
+ { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> }\r
+ ;\r
+\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// date year varid = Date.Year, // "Date.Year" is a special case we recognize\r
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+// help = STRING_TOKEN(STR_DATE_YEAR_HELP),\r
+// minimum = 1939,\r
+// maximum = 2101,\r
+// step = 1,\r
+// default = 1964,\r
+//\r
+// month varid = Date.Month, \r
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+// help = STRING_TOKEN(STR_DATE_MONTH_HELP),\r
+// minimum = 1,\r
+// maximum = 12,\r
+// step = 1,\r
+// default = 1,\r
+//\r
+// day varid = Date.Day,\r
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+// help = STRING_TOKEN(STR_DATE_DAY_HELP),\r
+// minimum = 1,\r
+// maximum = 31,\r
+// step = 0x1,\r
+// default = 1,\r
+//\r
+// enddate;\r
+// \r
+vfrStatementDate : \r
+ Date \r
+ IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>\r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement \r
+ IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>\r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement \r
+ IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >> \r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement \r
+ EndDate ";"\r
+ ;\r
+ \r
+vfrStatementTime : \r
+ Time \r
+ IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>\r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement \r
+ IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>\r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement \r
+ IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>\r
+ vfrStructFieldName[2] "," \r
+ dateTimeSubStatement\r
+ EndTime ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// text text = STRING_ID;\r
+// text text = STRING_ID, text = STRING_ID;\r
+// text text = STRING_ID, text = STRING_ID, flags = x, key = y;\r
+//\r
+vfrStatementTextText :\r
+ << ResetFlags (); >>\r
+ IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>\r
+ Help "=" getStringId ","\r
+ Text "=" \r
+ getStringId // writes string identifier\r
+ { "," Text "=" getStringId\r
+ "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >>\r
+ "," \r
+ Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>\r
+ }\r
+ ";" \r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// inventory help = ID, text = ID;\r
+// inventory help = ID, text = id, text = ID;\r
+//\r
+vfrStatementInventory :\r
+ IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>\r
+ Help "=" getStringId ","\r
+ Text "=" getStringId // writes string identifier\r
+ { "," Text "=" getStringId\r
+ }\r
+ ";" \r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// restore defaults,\r
+// formid = 4,\r
+// prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),\r
+// help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),\r
+// flags = 0,\r
+// key = 0;\r
+//\r
+// save defaults,\r
+// formid = 4,\r
+// prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),\r
+// help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),\r
+// flags = 0,\r
+// key = 0;\r
+//\r
+vfrStatementSaveRestoreDefaults : \r
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>\r
+ ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>\r
+ | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>\r
+ )\r
+ Defaults ","\r
+ FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2)); \r
+ AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());\r
+ >>\r
+ Prompt "=" getStringId ","\r
+ KH:Help "=" getStringId << LineNum = KH->getLine(); >>\r
+ { \r
+ "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>\r
+ }\r
+ {\r
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK\r
+//\r
+// \r
+flagsField :\r
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>\r
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>\r
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>\r
+ | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >>\r
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>\r
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>\r
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>\r
+ ;\r
+\r
+dateTimeSubStatement :\r
+ Prompt "=" getStringId ","\r
+ Help "=" getStringId ","\r
+ << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key\r
+ minMaxStepDefault << WriteMinMaxStepDefault (); >>\r
+ ;\r
+ \r
+vfrStatementCheckBox : \r
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>\r
+ IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>\r
+ VarId "=" vfrStructFieldName[1] ","\r
+ Prompt "=" getStringId ","\r
+ Help "=" getStringId ","\r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>\r
+ { \r
+ Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>\r
+ }\r
+ << WriteFlagsKey (KeyValue, LineNum); >>\r
+ EndCheckBox ";"\r
+ ;\r
+ \r
+vfrStatementSubTitle :\r
+ IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>\r
+ getStringId // writes string indentifier\r
+ ";"\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// banner \r
+// title = STRING_TOKEN(STR_BANNER_TITLE),\r
+// line 1,\r
+// align center; // or left or right\r
+//\r
+// banner, \r
+// title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;\r
+//\r
+vfrStatementBanner :\r
+ IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>\r
+ Title "=" getStringId ","\r
+ ( \r
+ Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>\r
+ Align \r
+ ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>\r
+ | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>\r
+ | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>\r
+ ) ";"\r
+ |\r
+ Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>\r
+ << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>\r
+ )\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// oneof varid = MyNv.OneOfData,\r
+// prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+// help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+// option text = STRING_TOKEN(STR_ONE_OF_TEXT), \r
+// value = 0, \r
+// flags = DEFAULT | INTERACTIVE;\r
+//\r
+// supressif/grayoutif are supported inside oneof stmt.\r
+// We do not restrict the number of oneOfOptionText to >=2, but >=1.\r
+// The situation that all oneOfOptionText are suppressed is also possiable.\r
+//\r
+vfrStatementOneOf :\r
+ << ResetFlags (); >>\r
+ IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>\r
+ VarId "=" vfrStructFieldName[2] "," \r
+ Prompt "=" getStringId "," // writes string identifier\r
+ Help "=" getStringId "," // writes string identifier\r
+ ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2.\r
+ IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// \r
+// orderedlist varid = MyNv.OrderedListData,\r
+// prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),\r
+// help = STRING_TOKEN(STR_ORDERED_LIST_HELP), \r
+// option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;\r
+// -- additional option text -- \r
+// endlist;\r
+//\r
+vfrStatementOrderedList :\r
+ << ResetFlags (); InitOrderedList(); >>\r
+ IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>\r
+ VarId "=" vfrStructFieldNameArray[1] "," \r
+ Prompt "=" getStringId "," // writes string identifier\r
+ Help "=" getStringId "," // writes string identifier\r
+ orderedListOptionText ( orderedListOptionText )+\r
+ IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;\r
+//\r
+// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to\r
+// be set, and value cannot be 0.\r
+//\r
+orderedListOptionText :\r
+ << UINT32 KeyValue = 0; >>\r
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>\r
+ Text "=" getStringId "," // writes string identifier\r
+ Value "=" WVAL:Number "," << \r
+ if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {\r
+ PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL); \r
+ } else {\r
+ WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2)); \r
+ }\r
+ >>\r
+ FF:Flags "=" orderedListFlagsField \r
+ ("\|" orderedListFlagsField )* \r
+ { \r
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> \r
+ }\r
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>\r
+ ";" << mOptionCount++; >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK\r
+//\r
+// The ordered list flags field cannot have a default.\r
+//\r
+orderedListFlagsField :\r
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>\r
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>\r
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>\r
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>\r
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>\r
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>\r
+ | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>\r
+ ;\r
+\r
+//\r
+// Parse references to VFR structure field names of form "MyNvStructure.Field". \r
+// This implementation is specific to strings, passwords, and references in an \r
+// ordered list statement because we want to specify the size of the entire \r
+// field, rather than just one element. Then call a function to write out its \r
+// offset and length.\r
+//\r
+vfrStructFieldNameArray[int FieldWidth] :\r
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>\r
+ SName:StringIdentifier \r
+ "." \r
+ SFieldName:StringIdentifier \r
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }\r
+ << \r
+ WriteFieldOffset (1, \r
+ SName->getText(), \r
+ SName->getLine(), \r
+ SFieldName->getText(), \r
+ SFieldName->getLine(),\r
+ ArrayIndex, \r
+ IsArrayIndex,\r
+ FieldWidth,\r
+ 1\r
+ ); \r
+ >>\r
+ ;\r
+\r
+//\r
+// Parse references to VFR structure field names of form "MyNvStructure.Field",\r
+// then call a function to write out its offset and length.\r
+//\r
+vfrStructFieldName[int FieldWidth] :\r
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>\r
+ SName:StringIdentifier \r
+ "." \r
+ SFieldName:StringIdentifier \r
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }\r
+ << \r
+ WriteFieldOffset (1, \r
+ SName->getText(), \r
+ SName->getLine(), \r
+ SFieldName->getText(), \r
+ SFieldName->getLine(),\r
+ ArrayIndex, \r
+ IsArrayIndex,\r
+ FieldWidth,\r
+ 0\r
+ ); \r
+ >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+//\r
+// MyNvStructure.FieldName[4]\r
+//\r
+// Parse references to VFR structure field names of form "MyNvStructure.Field",\r
+// then call a function to write out the offset with no length.\r
+//\r
+vfrStructFieldNameNL[int FieldWidth] :\r
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>\r
+ SName:StringIdentifier \r
+ "." \r
+ SFieldName:StringIdentifier \r
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }\r
+ << \r
+ WriteFieldOffset (0, \r
+ SName->getText(), \r
+ SName->getLine(), \r
+ SFieldName->getText(), \r
+ SFieldName->getLine(),\r
+ ArrayIndex, \r
+ IsArrayIndex,\r
+ FieldWidth,\r
+ 0\r
+ ); \r
+ >>\r
+ ;\r
+\r
+//*****************************************************************************\r
+//\r
+// PARSE:\r
+// suppressif TRUE OR FALSE;\r
+// grayoutif FALSE OR TRUE;\r
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;\r
+// option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;\r
+// endif;\r
+//\r
+oneOfOptionText :\r
+ suppressIfOptionText |\r
+ grayOutIfOptionText |\r
+ commonOptionText\r
+ ;\r
+\r
+suppressIfOptionText : \r
+ << ResetFlags (); >>\r
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","\r
+ }\r
+ << WriteFlags (); >> // write the flags field \r
+ vfrBooleanExpression\r
+ ";"\r
+ { suppressIfGrayOutIf } ( commonOptionText )+\r
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>\r
+ ;\r
+\r
+grayOutIfOptionText :\r
+ << ResetFlags (); >>\r
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>\r
+ { \r
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," \r
+ }\r
+ << WriteFlags (); >> // write the flags field\r
+ vfrBooleanExpression\r
+ ";"\r
+ { grayoutIfSuppressIf } ( commonOptionText )+ \r
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>\r
+ ;\r
+\r
+commonOptionText : \r
+ << UINT32 KeyValue = 0; >>\r
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>\r
+ Text "=" getStringId "," // writes string identifier\r
+ Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>\r
+ FF:Flags "=" flagsField ("\|" flagsField )* \r
+ { \r
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> \r
+ }\r
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>\r
+ ";" << mOptionCount++; >>\r
+ ;\r
+\r
+//\r
+// Gets a string identifier. It must be a numeric value of form:\r
+// \r
+// STRING_TOKEN(100)\r
+//\r
+getStringId :\r
+ << unsigned short StrId; >>\r
+ StringToken OpenParen\r
+ IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >> \r
+ CloseParen\r
+ ;\r
+\r
+//******************************************************************************\r
+//\r
+// Parser class definition. \r
+// \r
+class EfiVfrParser {\r
+<<\r
+//\r
+// Parser definitions go here \r
+//\r
+private:\r
+ STRUCT_DEFINITION *mFirstStructDefinition;\r
+ STRUCT_DEFINITION *mLastStructDefinition;\r
+ INT32 mNvDataStructSize; \r
+ INT32 mNonNvDataStructSize;\r
+ //\r
+ // Flag to indicate that we're processing a ideqid VFR statement so that\r
+ // we can do late checks on the statement.\r
+ //\r
+ INT32 mIdEqIdStmt;\r
+ INT32 mLastNVVariableDataSize;\r
+ GOTO_REFERENCE *mGotoReferences;\r
+ FORM_ID_VALUE *mFormIdValues;\r
+ VfrOpcodeHandler mOpcodeHandler;\r
+ UINT16_LIST *mUint16List;\r
+ UINT16_LIST *mLastUint16;\r
+ UINT16_LIST *mDefinedLabels;\r
+ UINT16_LIST *mDefinedVarStoreId;\r
+ UINT16_LIST *mLastDefinedVarStoreId;\r
+ UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;\r
+ UINT32 mStmtFlags;\r
+ UINT32 mSubStmtFlags;\r
+ UINT32 mSubStmtFlagsLineNum;\r
+ EFI_GUID mFormSetGuid;\r
+ UINT8 mNvDataStructDefined;\r
+ UINT16 mClass, mSubclass;\r
+ UINT32 mIfStart;\r
+ UINT32 mOptionCount; // how many "option" fields in a given statement\r
+ UINT32 mLastVarIdSize;\r
+ UINT8 mOutput;\r
+public: \r
+\r
+VOID \r
+EfiVfrParser::SetIfStart (\r
+ UINT32 LineNum\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Invoked during VFR parsing when an "if" is encountered. Save the\r
+ source line number so we can point to it if we don't find a \r
+ corresponding endif later.\r
+\r
+Arguments:\r
+ LineNum - source line number where the "if" was parsed.\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ mIfStart = LineNum;\r
+}\r
+VOID \r
+EfiVfrParser::SetClass (\r
+ UINT32 LineNum, \r
+ UINT32 Value\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+ Invoked during VFR parsing when a "class" statement is found. Check the\r
+ range on the class value and save it for later.\r
+\r
+Arguments:\r
+ LineNum - source line number where the class statement was parsed.\r
+ Value - the class value\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Value & 0xFFFF0000) {\r
+ PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");\r
+ }\r
+ mClass |= (UINT16)Value;\r
+}\r
+VOID \r
+EfiVfrParser::SetSubclass (\r
+ UINT32 LineNum, \r
+ UINT32 Value\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+ Invoked during VFR parsing when a subclass statement is found. Check the\r
+ range on the value and save it for later.\r
+\r
+Arguments:\r
+ LineNum - source line number where the class statement was parsed.\r
+ Value - the subclass value from the VFR statement\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Value & 0xFFFF0000) {\r
+ PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");\r
+ }\r
+ mSubclass |= (UINT16)Value;\r
+}\r
+VOID EfiVfrParser::WriteClass ()\r
+{\r
+ WriteWord (mClass);\r
+ mClass = 0;\r
+}\r
+VOID EfiVfrParser::WriteSubclass ()\r
+{\r
+ WriteWord (mSubclass);\r
+ mSubclass = 0;\r
+}\r
+VOID EfiVfrParser::WriteIfrBytes ()\r
+{\r
+ mOpcodeHandler.WriteIfrBytes ();\r
+}\r
+VOID \r
+EfiVfrParser::WriteFlagsKey (\r
+ UINT32 KeyValue, \r
+ UINT32 LineNum\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+ Write out the flags and key values from the previous VFR statement.\r
+ Many statements take a flags/key pair. If not specified, then 0\r
+ values are written out. However do not allow an interactive flags field\r
+ to be specified if no key value is specified. Also, if NV_ACCESS flag\r
+ is set but INTERACTIVE is not, then set interactive and issue a warning.\r
+\r
+Arguments:\r
+ KeyValue - the key value from the VFR statement\r
+ LineNum - source line number where the statement was parsed\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {\r
+ PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");\r
+ }\r
+ if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {\r
+ PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");\r
+ mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;\r
+ }\r
+ WriteFlags ();\r
+ WriteWord (KeyValue);\r
+}\r
+VOID \r
+EfiVfrParser::InitOrderedList ()\r
+{\r
+ mOptionCount = 0;\r
+} \r
+VOID \r
+EfiVfrParser::EndOrderedList (\r
+ UINT32 LineNum\r
+ )\r
+{\r
+ if (mLastVarIdSize < mOptionCount) {\r
+ PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::ResetFlags ()\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Flags are set for each substatement in a given one-of statement.\r
+ To make sure there are no conflicts, for example setting DEFAULT on\r
+ more than one substatement, we keep track of the flags at a statement\r
+ level and a substatement level. This function resets the flags so \r
+ we get a fresh start.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ mStmtFlags = 0;\r
+ mSubStmtFlagsLineNum = 0;\r
+ mSubStmtFlags = 0;\r
+}\r
+//\r
+// Test validity of flags value for a one-of statement.\r
+//\r
+VOID \r
+EfiVfrParser::TestOneOfFlags (\r
+ UINT32 LineNum\r
+ ) \r
+{\r
+ //\r
+ // One of the fields must have had the default bit set\r
+ //\r
+ if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {\r
+ PrintWarningMessage (LineNum, "default value must be specified", NULL);\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::SetFlags (\r
+ UINT32 Flags, \r
+ UINT32 LineNum\r
+ ) \r
+{\r
+ //\r
+ // Check for redefinitions and invalid combinations\r
+ //\r
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {\r
+ PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");\r
+ }\r
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {\r
+ PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");\r
+ }\r
+ mSubStmtFlags |= Flags;\r
+ mSubStmtFlagsLineNum = LineNum;\r
+}\r
+VOID \r
+EfiVfrParser::WriteFlags ()\r
+{\r
+ //\r
+ // Check value for validity\r
+ //\r
+ if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT | \r
+ EFI_IFR_FLAG_MANUFACTURING | \r
+ EFI_IFR_FLAG_INTERACTIVE | \r
+ EFI_IFR_FLAG_NV_ACCESS | \r
+ EFI_IFR_FLAG_RESET_REQUIRED | \r
+ EFI_IFR_FLAG_LATE_CHECK )) {\r
+ PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);\r
+ }\r
+ WriteByte ((UINT8)mSubStmtFlags, 'F');\r
+ //\r
+ // We can now clear the substatement flags\r
+ //\r
+ mStmtFlags |= mSubStmtFlags;\r
+ mSubStmtFlags = 0;\r
+}\r
+//\r
+// When we parse a min/max/step/default sequence, save off the values for\r
+// later use. Call this first to init the values.\r
+//\r
+VOID \r
+EfiVfrParser::InitMinMaxStepDefault ()\r
+{\r
+ mMinimumValue = 0;\r
+ mMaximumValue = 0;\r
+ mStepValue = 1;\r
+ mDefaultValue = 0;\r
+} \r
+VOID \r
+EfiVfrParser::WriteMinMaxStepDefault ()\r
+{\r
+ WriteWord (mMinimumValue);\r
+ WriteWord (mMaximumValue);\r
+ WriteWord (mStepValue);\r
+ WriteWord (mDefaultValue);\r
+} \r
+VOID \r
+EfiVfrParser::SetMinMaxStepDefault (\r
+ UINT16 Value, \r
+ INT32 MMSD, \r
+ INT32 LineNum\r
+ ) \r
+{\r
+ UINT16 TempValue;\r
+ //\r
+ // Min specified\r
+ //\r
+ if (MMSD == 0) {\r
+ mMinimumValue = Value;\r
+ mDefaultValue = Value;\r
+ //\r
+ // Max specified\r
+ //\r
+ } else if (MMSD == 1) {\r
+ mMaximumValue = Value;\r
+ //\r
+ // If min > max, then swap the values. That includes resetting the default\r
+ // value as well.\r
+ //\r
+ if (mMinimumValue > mMaximumValue) {\r
+ PrintWarningMessage (LineNum, NULL, "maximum < minimum"); \r
+ TempValue = Value;\r
+ mMaximumValue = mMinimumValue;\r
+ mMinimumValue = TempValue;\r
+ mDefaultValue = mMinimumValue;\r
+ }\r
+ //\r
+ // Step specified\r
+ //\r
+ } else if (MMSD == 2) { \r
+ mStepValue = Value;\r
+ //\r
+ // Default specified. Make sure min <= default <= max.\r
+ //\r
+ } else if (MMSD == 3) {\r
+ mDefaultValue = Value;\r
+ if (mMinimumValue > Value) {\r
+ PrintErrorMessage (LineNum, NULL, "default value < minimum value");\r
+ } else if (Value > mMaximumValue) {\r
+ PrintErrorMessage (LineNum, NULL, "default value > maximum value");\r
+ }\r
+ } else {\r
+ PrintErrorMessage (LineNum, "application error", "internal MMSD error"); \r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::AddLabel (\r
+ UINT32 LabelNumber, \r
+ UINT32 LineNum\r
+ ) \r
+{\r
+ UINT16_LIST *Label;\r
+\r
+ //\r
+ // Added a label from the user VFR script. Make sure they haven't already \r
+ // defined the same label elsewhere\r
+ //\r
+ for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {\r
+ if (Label->Value == LabelNumber) {\r
+ PrintErrorMessage (LineNum, NULL, "label already defined");\r
+ PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");\r
+ break;\r
+ }\r
+ }\r
+ Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));\r
+ if (Label == NULL) {\r
+ PrintErrorMessage (0, NULL, "memory allocation error");\r
+ return;\r
+ }\r
+ memset ((char *)Label, 0, sizeof (UINT16_LIST));\r
+ Label->Value = LabelNumber;\r
+ Label->LineNum = LineNum;\r
+ Label->Next = mDefinedLabels;\r
+ mDefinedLabels = Label;\r
+}\r
+VOID \r
+EfiVfrParser::QueueIdEqValList (\r
+ UINT16 Value\r
+ )\r
+{\r
+ UINT16_LIST *U16;\r
+ \r
+ U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));\r
+ if (U16 == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");\r
+ } else {\r
+ memset ((char *)U16, 0, sizeof (UINT16_LIST));\r
+ U16->Value = Value;\r
+ if (mUint16List == NULL) {\r
+ mUint16List = U16;\r
+ } else {\r
+ mLastUint16->Next = U16;\r
+ } \r
+ mLastUint16 = U16;\r
+ }\r
+} \r
+VOID \r
+EfiVfrParser::FlushQueueIdEqValList ()\r
+{\r
+ UINT32 Count;\r
+ \r
+ //\r
+ // We queued up a list of IdEqValList items. The IFR requires a count\r
+ // followed by the actual values. Do it.\r
+ //\r
+ Count = 0;\r
+ mLastUint16 = mUint16List;\r
+ while (mLastUint16 != NULL) {\r
+ Count++;\r
+ mLastUint16 = mLastUint16->Next;\r
+ }\r
+ // BUGBUG -- check for more than 16K items?\r
+ WriteWord (Count);\r
+ //\r
+ // Now write the values.\r
+ //\r
+ mLastUint16 = mUint16List;\r
+ while (mLastUint16 != NULL) {\r
+ WriteWord ((UINT32)mLastUint16->Value);\r
+ mLastUint16 = mLastUint16->Next;\r
+ }\r
+ //\r
+ // Free up the list\r
+ // \r
+ mLastUint16 = mUint16List;\r
+ while (mUint16List != NULL) {\r
+ mLastUint16 = mUint16List->Next;\r
+ free (mUint16List);\r
+ mUint16List = mLastUint16;\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::PrintErrorMessage (\r
+ UINT32 LineNum,\r
+ INT8 *Msg1,\r
+ INT8 *Msg2\r
+ )\r
+{\r
+ char *FileName;\r
+ \r
+ if (LineNum != 0) {\r
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);\r
+ Error (FileName, LineNum, 0, Msg1, Msg2);\r
+ } else {\r
+ Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::PrintWarningMessage (\r
+ UINT32 LineNum,\r
+ INT8 *Msg1,\r
+ INT8 *Msg2\r
+ )\r
+{\r
+ char *FileName;\r
+ \r
+ if (LineNum != 0) {\r
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);\r
+ Warning (FileName, LineNum, 0, Msg1, Msg2);\r
+ } else {\r
+ Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::syn (\r
+ ANTLRAbstractToken *Tok, \r
+ ANTLRChar *Egroup, \r
+ SetWordType *Eset, \r
+ ANTLRTokenType ETok, \r
+ INT32 Huh\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Called by the parser base class as a result of parse syntax errors.\r
+\r
+Arguments:\r
+ Tok - token that caused the error\r
+ Egroup - not sure\r
+ Eset - index in token table of the expected token\r
+ Huh - not sure\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ char *FileName;\r
+ UINT32 LineNum;\r
+ \r
+ LineNum = Tok->getLine ();\r
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);\r
+ //\r
+ // Sometimes the token number is 0, in which case I don't know what to\r
+ // print.\r
+ //\r
+ if (ETok == 0) {\r
+ Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");\r
+ } else {\r
+ //\r
+ // If we were expecting an endif, then report the line where the corresponding\r
+ // IF began.\r
+ //\r
+ if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {\r
+ LineNum = mIfStart;\r
+ FileName = ConvertLineNumber (&LineNum);\r
+ Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);\r
+ } else {\r
+ Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);\r
+ }\r
+ }\r
+}\r
+\r
+VOID \r
+EfiVfrParser::init() \r
+/*++\r
+\r
+Routine Description:\r
+ Initializations function for our parser.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ ANTLRParser::init();\r
+\r
+ //\r
+ // Used for queuing a variable list of UINT16's\r
+ //\r
+ mUint16List = NULL;\r
+ mLastUint16 = NULL;\r
+ mFirstStructDefinition = NULL;\r
+ mLastStructDefinition = NULL;\r
+ mNvDataStructSize = 0;\r
+ mNonNvDataStructSize = 0;\r
+ mNvDataStructDefined = 0;\r
+ mGotoReferences = NULL;\r
+ mFormIdValues = NULL;\r
+ mDefinedLabels = NULL;\r
+ mClass = 0;\r
+ mSubclass = 0;\r
+ mIfStart = 0;\r
+ mDefinedVarStoreId = NULL;\r
+ mLastDefinedVarStoreId = NULL;\r
+ mIdEqIdStmt = 0;\r
+ mLastNVVariableDataSize = 0;\r
+ \r
+ memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));\r
+}\r
+//\r
+// Destructor for the parser.\r
+//\r
+EfiVfrParser::~EfiVfrParser(VOID)\r
+{\r
+ Cleanup();\r
+}\r
+VOID\r
+EfiVfrParser::Cleanup (VOID)\r
+/*++\r
+\r
+Routine Description:\r
+ Free memory allocated during parsing\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ STRUCT_DEFINITION *NextStruct;\r
+ STRUCT_FIELD_DEFINITION *NextField;\r
+ UINT8 Buff[6];\r
+ UINT16_LIST *NextU16List;\r
+ \r
+ //\r
+ // Free up the structure definitions if any\r
+ //\r
+ while (mFirstStructDefinition != NULL) {\r
+ //\r
+ // Free up all the fields for this struct\r
+ //\r
+ while (mFirstStructDefinition->Field != NULL) {\r
+ NextField = mFirstStructDefinition->Field->Next;\r
+ free (mFirstStructDefinition->Field->Name);\r
+ free (mFirstStructDefinition->Field);\r
+ mFirstStructDefinition->Field = NextField;\r
+ }\r
+ NextStruct = mFirstStructDefinition->Next;\r
+ free (mFirstStructDefinition->Name);\r
+ free (mFirstStructDefinition);\r
+ mFirstStructDefinition = NextStruct;\r
+ }\r
+ //\r
+ // Free up the goto references and form id defines\r
+ //\r
+ FreeGotoReferences ();\r
+ //\r
+ // Free up label list\r
+ //\r
+ while (mDefinedLabels != NULL) {\r
+ NextU16List = mDefinedLabels->Next;\r
+ delete (mDefinedLabels);\r
+ mDefinedLabels = NextU16List;\r
+ }\r
+ //\r
+ // Free up the list of defined variable storage IDs\r
+ //\r
+ while (mDefinedVarStoreId != NULL) {\r
+ NextU16List = mDefinedVarStoreId->Next;\r
+ delete (mDefinedVarStoreId);\r
+ mDefinedVarStoreId = NextU16List;\r
+ }\r
+}\r
+\r
+INT32 \r
+EfiVfrParser::AtoX (\r
+ INT8 *HexString, \r
+ INT32 NumBytes, \r
+ UINT32 *HexValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Given a pointer to a ascii hex string, convert to a number with the given\r
+ number of bytes.\r
+\r
+Arguments:\r
+ HexString - pointer to a string of format 30BCA\r
+ Size - number of bytes to convert\r
+ HexValue - return result\r
+\r
+Returns:\r
+ The number of bytes converted.\r
+\r
+--*/\r
+{\r
+ INT32 Count;\r
+ INT32 Value;\r
+\r
+ *HexValue = 0;\r
+ Count = 0;\r
+ while (Count < NumBytes) {\r
+ if ((*HexString >= '0') && (*HexString <= '9')) {\r
+ Value = *HexString - '0';\r
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {\r
+ Value = *HexString - 'a' + 10;\r
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {\r
+ Value = *HexString - 'A' + 10;\r
+ } else {\r
+ return Count;\r
+ }\r
+ HexString++;\r
+ *HexValue = (*HexValue << 4) | Value;\r
+ if ((*HexString >= '0') && (*HexString <= '9')) {\r
+ Value = *HexString - '0';\r
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {\r
+ Value = *HexString - 'a' + 10;\r
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {\r
+ Value = *HexString - 'A' + 10;\r
+ } else {\r
+ return Count;\r
+ }\r
+ *HexValue = (*HexValue << 4) | Value;\r
+ HexString++;\r
+ Count++;\r
+ }\r
+ return Count;\r
+}\r
+VOID \r
+EfiVfrParser::WriteGuidValue (\r
+ UINT32 TokenLineNum,\r
+ INT8 *G1, \r
+ INT8 *G2,\r
+ INT8 *G3,\r
+ INT8 *G4,\r
+ INT8 *G5,\r
+ INT8 *G6,\r
+ INT8 *G7,\r
+ INT8 *G8,\r
+ INT8 *G9,\r
+ INT8 *G10,\r
+ INT8 *G11\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ A Guid was parsed, likely of format:\r
+ #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }\r
+\r
+ Write out the value.\r
+\r
+Arguments:\r
+ TokenLineNum - line number where the guid was used\r
+ G1-G11 - the 11 fields of the guid value\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINT32 Value;\r
+ INT32 Loop;\r
+ INT8 *Cptr;\r
+\r
+ mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);\r
+ mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);\r
+ mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);\r
+ mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);\r
+ mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);\r
+ \r
+ WriteDWord (mFormSetGuid.Data1, 'G');\r
+ WriteWord (mFormSetGuid.Data2);\r
+ WriteWord (mFormSetGuid.Data3);\r
+ WriteByte (mFormSetGuid.Data4[0], 0);\r
+ WriteByte (mFormSetGuid.Data4[1], 0);\r
+ WriteByte (mFormSetGuid.Data4[2], 0);\r
+ WriteByte (mFormSetGuid.Data4[3], 0);\r
+ WriteByte (mFormSetGuid.Data4[4], 0);\r
+ WriteByte (mFormSetGuid.Data4[5], 0);\r
+ WriteByte (mFormSetGuid.Data4[6], 0);\r
+ WriteByte (mFormSetGuid.Data4[7], 0);\r
+}\r
+VOID \r
+EfiVfrParser::WriteFieldOffset (\r
+ INT8 WriteLength,\r
+ INT8 *StructName, \r
+ INT32 LineNum1, \r
+ INT8 *FieldName, \r
+ INT32 LineNum2,\r
+ INT32 ArrayIndex,\r
+ INT8 IsArrayIndex,\r
+ INT32 FieldWidth,\r
+ INT8 WriteArraySize\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+ A VFR script referenced the NV store structure. Given the structure's name\r
+ and the field's name, write the offset of the field to the output file.\r
+\r
+Arguments:\r
+ WriteLength - write the field length byte out\r
+ StructName - name of the NV store structure\r
+ LineNum1 - line number in the VFR where we are (for error printing)\r
+ FieldName - the name of the field within the NV store structure\r
+ LineNum2 - line number in the VFR where FieldName is referenced \r
+ ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex]\r
+ IsArrayIndex - non-zero if an array index was specified\r
+ FieldWidth - expected size for the Field (1 byte? 2 bytes?)\r
+ WriteArraySize - write the size of the entire field, not the size of a single element\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ STRUCT_DEFINITION *StructDef;\r
+ STRUCT_FIELD_DEFINITION *FieldDef;\r
+ UINT32 Offset;\r
+ UINT32 VarSize;\r
+ INT8 Msg[100];\r
+ //\r
+ // If we're writing an array size, then they better have referenced the field without an\r
+ // index. \r
+ //\r
+ if (WriteArraySize && IsArrayIndex) {\r
+ sprintf (Msg, "array index specified where an array is required");\r
+ PrintErrorMessage (LineNum2, FieldName, Msg);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // The reference index starts at 1 not 0\r
+ //\r
+ if (IsArrayIndex && (ArrayIndex < 1)) {\r
+ printf ("WARNING: array index shouldn't be less than 1");\r
+ }\r
+ //\r
+ // Look through our list of known structures for a match\r
+ //\r
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {\r
+ //\r
+ // Check for matching structure name\r
+ //\r
+ if (strcmp (StructDef->Name, StructName) == 0) {\r
+ //\r
+ // Mark it as referenced (for debug purposes only). Check the\r
+ // flag that indicates that we have already found a varstore VFR\r
+ // statement for it.\r
+ //\r
+ StructDef->Referenced++;\r
+ if (StructDef->VarStoreIdValid == 0) {\r
+ //\r
+ // Set it valid so we don't flag it multiple times, then emit the error\r
+ //\r
+ StructDef->VarStoreIdValid = 1;\r
+ PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");\r
+ }\r
+ //\r
+ // Let the opcode-handler know which variable storage we're now using\r
+ //\r
+ if (mIdEqIdStmt) {\r
+ mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);\r
+ } else {\r
+ mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);\r
+ }\r
+ //\r
+ // Found matching structure name. Now find the matching field name\r
+ //\r
+ for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {\r
+ if (strcmp (FieldDef->Name, FieldName) == 0) {\r
+ //\r
+ // Make sure the variable size is valid\r
+ //\r
+ if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {\r
+ sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');\r
+ PrintErrorMessage (LineNum2, FieldName, Msg);\r
+ }\r
+ //\r
+ // If they specified an index (MyVfrData.FieldX[10]), then make sure that the\r
+ // data structure was declared as an array, and that the index is in bounds.\r
+ // If they did not specify an index, then we'll assume 0. This is required for\r
+ // strings.\r
+ //\r
+ if (IsArrayIndex) {\r
+ VarSize = FieldDef->DataSize;\r
+ if (FieldDef->IsArray == 0) {\r
+ PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");\r
+ return;\r
+ }\r
+ if (FieldDef->ArrayLength < ArrayIndex) {\r
+ PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");\r
+ return;\r
+ }\r
+ } else {\r
+ if (FieldDef->IsArray) {\r
+ VarSize = FieldDef->DataSize * FieldDef->ArrayLength;\r
+ } else {\r
+ VarSize = FieldDef->DataSize;\r
+ }\r
+ }\r
+ //\r
+ // If we're in the middle of a ideqid VFR statement, then this is the second\r
+ // variable ID that we're now processing. Make sure that its size is the same\r
+ // as the first variable.\r
+ // \r
+ if (mIdEqIdStmt) {\r
+ if (mLastVarIdSize != VarSize) {\r
+ PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");\r
+ return;\r
+ }\r
+ }\r
+ mLastVarIdSize = VarSize;\r
+ //\r
+ // If we're supposed to write an array size, then require it to be an array\r
+ //\r
+ if (WriteArraySize && !FieldDef->IsArray) {\r
+ PrintErrorMessage (LineNum2, FieldName, "array required");\r
+ return;\r
+ }\r
+ //\r
+ // Write the variable offset and size. If we're in the non-NV structure, then\r
+ // set the offset beyond the NV data structure size.\r
+ //\r
+ Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);\r
+ if (StructDef->IsNonNV) Offset += mNvDataStructSize; \r
+ WriteWord (Offset);\r
+ if (WriteLength) {\r
+ if (WriteArraySize) {\r
+ if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {\r
+ PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");\r
+ return;\r
+ }\r
+ WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);\r
+ } else {\r
+ WriteByte (FieldDef->DataSize, 0);\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ }\r
+ sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);\r
+ PrintErrorMessage (LineNum2, Msg, NULL);\r
+ PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);\r
+ return;\r
+ }\r
+ }\r
+ //\r
+ // The structure was not found in the defined list. See if it's the "Date" structure\r
+ //\r
+ if (strcmp (StructName, "Date") == 0) {\r
+ //\r
+ // BUGBUG -- remove support for Date and Time as valid structure \r
+ // names. They should use the NON_NV_DATA_MAP structure for this.\r
+ //\r
+ // Someone specified Date.Years|Months|Days\r
+ // BUGBUG -- define some constants for the IDs used here\r
+ // Length == 0 implies that this is not user NV data storage.\r
+ //\r
+ if (strcmp (FieldName, "Year") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else if (strcmp (FieldName, "Month") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else if (strcmp (FieldName, "Day") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else {\r
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");\r
+ }\r
+ return;\r
+ } else if (strcmp (StructName, "Time") == 0) {\r
+ //\r
+ // Someone specified Time.Hours|Minutes|Seconds\r
+ // BUGBUG -- define some constants for the IDs used here\r
+ //\r
+ if (strcmp (FieldName, "Hours") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else if (strcmp (FieldName, "Minutes") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else if (strcmp (FieldName, "Seconds") == 0) {\r
+ //\r
+ // Write ID (offset), ID, and size\r
+ //\r
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);\r
+ if (WriteLength) {\r
+ WriteByte (0, 0);\r
+ }\r
+ } else {\r
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");\r
+ }\r
+ return;\r
+ } else {\r
+ PrintErrorMessage (LineNum1, StructName, "undefined structure");\r
+ return;\r
+ }\r
+}\r
+VOID\r
+EfiVfrParser::StartStructDefinition (\r
+ INT32 IsNonNV,\r
+ INT32 LineNum\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Called when we encounter a new "struct _MY_STRUCT..." statement while parsing. \r
+ Initialize internal data and structures for parsing the fields of the structure.\r
+\r
+Arguments:\r
+ LineNum - line number in the source file (for error reporting purposes)\r
+ IsNonNv - flag indicating (if nonzero) that the variable referred to is not in\r
+ the standard NV store.\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ STRUCT_DEFINITION *StructDef;\r
+ //\r
+ // Allocate memory for the structure record\r
+ //\r
+ StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));\r
+ memset (StructDef, 0, sizeof (STRUCT_DEFINITION));\r
+ StructDef->LineNum = LineNum;\r
+ //\r
+ // Set flag indicating non-NV data structure or not\r
+ //\r
+ StructDef->IsNonNV = IsNonNV;\r
+ //\r
+ // Add it to the end of our linked list. If it's the first one\r
+ // defined, then it's the default varstore ID, so set it valid.\r
+ //\r
+ if (mFirstStructDefinition == NULL) {\r
+ mFirstStructDefinition = StructDef;\r
+ StructDef->VarStoreIdValid = 1;\r
+ } else {\r
+ mLastStructDefinition->Next = StructDef;\r
+ }\r
+ mLastStructDefinition = StructDef;\r
+}\r
+VOID\r
+EfiVfrParser::EndStructDefinition (\r
+ INT8 *StructName,\r
+ INT32 LineNum\r
+ )\r
+{\r
+ STRUCT_DEFINITION *StructDef;\r
+ STRUCT_FIELD_DEFINITION *FieldDef;\r
+ UINT32 Offset;\r
+ //\r
+ // Make sure they have not already defined a structure with this name\r
+ //\r
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {\r
+ if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {\r
+ PrintErrorMessage (LineNum, StructName, "structure with this name already defined");\r
+ //\r
+ // Fall through and fill in the rest of the structure information. We do\r
+ // this because the structure has already been added to our global list,\r
+ // so will be used elsewhere, so we want it to contain valid fields.\r
+ //\r
+ }\r
+ } \r
+ //\r
+ // Allocate memory for the structure name \r
+ //\r
+ mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);\r
+ strcpy (mLastStructDefinition->Name, StructName);\r
+ //\r
+ // Compute the structure size, and the offsets to each field\r
+ //\r
+ Offset = 0;\r
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {\r
+ FieldDef->Offset = Offset;\r
+ Offset += FieldDef->ArrayLength * FieldDef->DataSize;\r
+ }\r
+ mLastStructDefinition->Size = Offset;\r
+ //\r
+ // Go through all the structure we have so far and figure out (if we can)\r
+ // the size of the non-NV storage. We also assume that the first structure\r
+ // definition is the primary/default storage for the VFR form.\r
+ //\r
+ if (mNonNvDataStructSize == 0) {\r
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {\r
+ if (StructDef->IsNonNV) {\r
+ mNonNvDataStructSize = StructDef->Size;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (mNvDataStructSize == 0) {\r
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {\r
+ if (StructDef->IsNonNV == 0) {\r
+ mNvDataStructSize = StructDef->Size;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+VOID \r
+EfiVfrParser::AddStructField (\r
+ INT8 *FieldName, \r
+ INT32 LineNum, \r
+ INT32 DataSize,\r
+ INT32 ArrayLength,\r
+ INT8 IsArray\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+ We're parsing the VFR structure definition. Add another defined field to \r
+ our definition.\r
+\r
+Arguments:\r
+ FieldName - name of the field in the structure.\r
+ LineNum - the line number from the input (preprocessor output) file\r
+ DataSize - the size of the field (1, 2, or 4 bytes)\r
+ ArrayLength - the number of elements (for array)\r
+ IsArray - non-zero if the field is an array\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ STRUCT_FIELD_DEFINITION *FieldDef;\r
+ STRUCT_FIELD_DEFINITION *Temp;\r
+ //\r
+ // Make sure we don't already have a field of this name in our structure\r
+ //\r
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {\r
+ if (strcmp (FieldDef->Name, FieldName) == 0) {\r
+ PrintErrorMessage (LineNum, FieldName, "field with this name already defined");\r
+ return;\r
+ }\r
+ } \r
+ //\r
+ // If it's an array, then they better not have a size of 0. For example:\r
+ // UINT8 MyBytes[0];\r
+ //\r
+ if (IsArray && (ArrayLength <= 0)) {\r
+ PrintErrorMessage (LineNum, FieldName, "invalid array size");\r
+ return;\r
+ } \r
+ //\r
+ // Allocate memory for a new structure field definition\r
+ // \r
+ FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));\r
+ memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));\r
+ FieldDef->ArrayLength = ArrayLength;\r
+ FieldDef->DataSize = DataSize;\r
+ FieldDef->IsArray = IsArray;\r
+ FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);\r
+ strcpy (FieldDef->Name, FieldName);\r
+ //\r
+ // Add it to the end of the field list for the currently active structure\r
+ //\r
+ if (mLastStructDefinition->Field == NULL) {\r
+ mLastStructDefinition->Field = FieldDef;\r
+ } else {\r
+ mLastStructDefinition->LastField->Next = FieldDef;\r
+ }\r
+ mLastStructDefinition->LastField = FieldDef;\r
+}\r
+VOID\r
+EfiVfrParser::AddVarStore (\r
+ INT8 *StructName, // actual name of the structure\r
+ INT8 *VarName, // actual NV variable name\r
+ UINT16 VarStoreId, // key value\r
+ INT32 LineNum // parse line number (for error reporting)\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Called while parsing a varstore statement. Add the variable store \r
+ to our linked list.\r
+\r
+Arguments:\r
+ StructName - the name of the typedef'ed structure to use\r
+ VarName - the NV variable name as specified in the varstore statement\r
+ VarStoreId - the variable store ID as specified in the varstore statememt\r
+ LineNum - the line number from the input (preprocessor output) file\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ STRUCT_DEFINITION *StructDef;\r
+ UINT16_LIST *L16Ptr;\r
+ //\r
+ // Go through our list of previously-defined variable store IDs and\r
+ // make sure this one is not a duplicate in name or key value.\r
+ //\r
+ for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {\r
+ if (L16Ptr->Value == VarStoreId) {\r
+ PrintErrorMessage (LineNum, "variable storage key already used", NULL);\r
+ PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);\r
+ }\r
+ }\r
+ // \r
+ // Key value of 0 is invalid since that's assigned by default to the default\r
+ // variable store (the first structure parsed).\r
+ //\r
+ if (VarStoreId == 0) {\r
+ PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);\r
+ }\r
+ //\r
+ // Create a new element to add to the list\r
+ //\r
+ L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));\r
+ memset (L16Ptr, 0, sizeof (UINT16_LIST));\r
+ L16Ptr->LineNum = LineNum;\r
+ L16Ptr->Value = VarStoreId;\r
+ if (mDefinedVarStoreId == NULL) {\r
+ mDefinedVarStoreId = L16Ptr;\r
+ } else {\r
+ mLastDefinedVarStoreId->Next = L16Ptr;\r
+ }\r
+ mLastDefinedVarStoreId = L16Ptr;\r
+ //\r
+ // Find the structure definition with this name\r
+ //\r
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {\r
+ if (strcmp (StructDef->Name, StructName) == 0) {\r
+ //\r
+ // Make sure they did not already define a variable storage ID \r
+ // for this structure.\r
+ //\r
+ if (StructDef->VarStoreId != 0) {\r
+ PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");\r
+ PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");\r
+ }\r
+ StructDef->VarStoreId = VarStoreId;\r
+ StructDef->VarStoreIdValid = 1;\r
+ StructDef->VarStoreLineNum = LineNum;\r
+ WriteWord (StructDef->Size);\r
+ while (*VarName) {\r
+ WriteByte(*VarName, 0);\r
+ VarName++;\r
+ }\r
+ WriteByte(0,0);\r
+ return;\r
+ }\r
+ } \r
+ PrintErrorMessage (LineNum, StructName, "structure with this name not defined");\r
+}\r
+VOID \r
+EfiVfrParser::WriteDWord (\r
+ UINT32 Value, \r
+ UINT8 KeyByte\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ During parsing, we came upon some code that requires a 32-bit value be\r
+ written to the VFR binary file. Queue up the 4 bytes.\r
+\r
+Arguments:\r
+ Value - the 32-bit value to write\r
+ KeyByte - a single character which gets written out beside the first byte.\r
+ This is used to tag the data in the output file so that during \r
+ debug you have an idea what the value is.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ //\r
+ // Write 4 bytes, little endian. Specify a key byte only on the first one\r
+ //\r
+ mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);\r
+ Value \>>= 8;\r
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);\r
+ Value \>>= 8;\r
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);\r
+ Value \>>= 8;\r
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);\r
+}\r
+VOID \r
+EfiVfrParser::WriteOpByte (\r
+ UINT32 LineNum,\r
+ UINT8 ByteValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ During parsing, we came upon a new VFR opcode. At this point we flush\r
+ the output queue and then queue up this byte (with 'O' for opcode tag).\r
+\r
+Arguments:\r
+\r
+ ByteValue - opcode value\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);\r
+}\r
+VOID \r
+EfiVfrParser::WriteByte (\r
+ UINT8 ByteValue, \r
+ UINT8 Key\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ During parsing of the VFR we spoonfeed this function with bytes to write to\r
+ the output VFR binary file. This function simply queues up the bytes, and\r
+ the queue gets flushed each time a new VFR opcode is encountered.\r
+\r
+Arguments:\r
+\r
+ ByteValue - raw byte to write\r
+ Key - character to tag the byte with when we write ByteValue to the\r
+ output file.\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ mOpcodeHandler.AddByte (ByteValue, Key);\r
+}\r
+VOID \r
+EfiVfrParser::WriteWord (\r
+ UINT32 Value\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ During VFR parsing we came upon a case where we need to write out a \r
+ 16-bit value. Queue it up.\r
+\r
+Arguments:\r
+ Value - value to write.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);\r
+ mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);\r
+}\r
+VOID \r
+EfiVfrParser::WriteStringIdWord (\r
+ UINT16 WordValue\r
+ )\r
+{\r
+ mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');\r
+ mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);\r
+}\r
+VOID\r
+EfiVfrParser::FreeGotoReferences ()\r
+/*++\r
+\r
+Routine Description:\r
+ Called during cleanup to free up the memory we allocated when\r
+ keeping track of VFR goto statements.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ GOTO_REFERENCE *CurrRef;\r
+ GOTO_REFERENCE *NextRef;\r
+ FORM_ID_VALUE *CurrFormId;\r
+ FORM_ID_VALUE *NextFormId;\r
+ UINT8 Found;\r
+ INT8 Name[20];\r
+\r
+ //\r
+ // Go through all the "goto" references and make sure there was a \r
+ // form ID of that value defined.\r
+ //\r
+ for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {\r
+ Found = 0;\r
+ for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {\r
+ if (CurrRef->Value == CurrFormId->Value) {\r
+ Found = 1;\r
+ break;\r
+ }\r
+ }\r
+ if (!Found) {\r
+ sprintf (Name, "%d", (UINT32)CurrRef->Value);\r
+ PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");\r
+ } \r
+ } \r
+ //\r
+ // Now free up the form id and goto references\r
+ //\r
+ CurrFormId = mFormIdValues;\r
+ while (CurrFormId != NULL) {\r
+ NextFormId = CurrFormId->Next;\r
+ free (CurrFormId);\r
+ CurrFormId = NextFormId;\r
+ }\r
+ mFormIdValues = NULL;\r
+ CurrRef = mGotoReferences;\r
+ while (CurrRef != NULL) {\r
+ NextRef = CurrRef->Next;\r
+ free (CurrRef);\r
+ CurrRef = NextRef;\r
+ } \r
+ mGotoReferences = NULL;\r
+}\r
+VOID\r
+EfiVfrParser::AddGotoReference (\r
+ UINT32 GotoNumber,\r
+ UINT32 LineNum\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ During VFR parsing we came upon a goto statement. Since we support\r
+ forward references, save the referenced label and at the end of parsing\r
+ we'll check that the label was actually defined somewhere.\r
+\r
+Arguments:\r
+ GotoNumber - the label number referenced\r
+ LineNum - the line number where the reference was made (used for\r
+ error reporting)\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ GOTO_REFERENCE *NewRef;\r
+ \r
+ NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));\r
+ if (NewRef == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");\r
+ return;\r
+ }\r
+ memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));\r
+ NewRef->Value = (UINT16)GotoNumber;\r
+ NewRef->RefLineNum = LineNum;\r
+ NewRef->Next = mGotoReferences;\r
+ mGotoReferences = NewRef;\r
+}\r
+VOID\r
+EfiVfrParser::AddFormId (\r
+ INT32 FormIdValue,\r
+ UINT32 LineNum\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This function is called when we parse "form formid = 3" statements.\r
+ We save the form ID valud so we can verify that duplicates are not\r
+ defined. Also, these are the targets of goto statements, so when we're\r
+ done parsing the script we also go through all the goto statements to\r
+ check that there was a target FormId defined as referenced by each\r
+ goto statement.\r
+ \r
+ Note that formid = 0 is invalid.\r
+\r
+Arguments:\r
+ FormIdValue - the parsed value for the Form ID\r
+ LineNum - line number of the source file we're parsing\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ FORM_ID_VALUE *NewFormId;\r
+ char *FileName;\r
+ char *FileName2;\r
+ UINT32 LineNum2; \r
+ //\r
+ // Verify that FormId != 0\r
+ //\r
+ if (FormIdValue == 0) {\r
+ FileName = ConvertLineNumber (&LineNum);\r
+ Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);\r
+ return;\r
+ }\r
+ //\r
+ // First go through all previously defined form IDs and make sure they have not defined\r
+ // duplicates.\r
+ //\r
+ for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {\r
+ if ((UINT16)FormIdValue == NewFormId->Value) {\r
+ FileName = ConvertLineNumber (&LineNum);\r
+ LineNum2 = NewFormId->LineNum;\r
+ FileName2 = ConvertLineNumber (&LineNum2);\r
+ Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);\r
+ Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);\r
+ return;\r
+ }\r
+ }\r
+ //\r
+ // Allocate memory for a new one \r
+ //\r
+ NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));\r
+ if (NewFormId == NULL) {\r
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");\r
+ return;\r
+ }\r
+ memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));\r
+ NewFormId->LineNum = LineNum;\r
+ NewFormId->Next = mFormIdValues;\r
+ NewFormId->Value = (UINT16)FormIdValue;\r
+ mFormIdValues = NewFormId;\r
+}\r
+UINT32\r
+EfiVfrParser::GetNumber (\r
+ INT8 *NumStr,\r
+ UINT32 LineNum,\r
+ UINT32 NumBytes\r
+ )\r
+{\r
+ UINT32 Value;\r
+ \r
+ if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {\r
+ AtoX (NumStr + 2, 4, &Value);\r
+ } else {\r
+ Value = (UINT32)atoi (NumStr);\r
+ }\r
+ //\r
+ // Check range\r
+ //\r
+ if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {\r
+ PrintErrorMessage (LineNum, NumStr, "value out of range");\r
+ return 0;\r
+ }\r
+ return Value;\r
+}\r
+\r
+>>\r
+\r
+} // end grammar class\r
+\r
+\r