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