Home | History | Annotate | Download | only in VfrCompile
      1 /*++
      2 
      3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   VfrCompile.g
     15 
     16 Abstract:
     17 
     18   PCCTS parser and lexer definitions for the EFI VFR forms compiler
     19 
     20 --*/
     21 
     22 #header<<
     23 
     24 #include "Tiano.h"
     25 #include "EfiUtilityMsgs.h"
     26 #include "EfiVfr.h"
     27 #include "VfrServices.h"
     28 #include EFI_PROTOCOL_DEFINITION (Hii)
     29 
     30 #include <ctype.h>
     31 #include <direct.h>
     32 #include <process.h> // for spawn functions
     33 
     34 >>
     35 
     36 <<
     37 
     38 //
     39 // Base info for DLG-generated scanner
     40 //
     41 #include "DLexerBase.h"
     42 
     43 //
     44 // Include the scanner file generated by DLG
     45 //
     46 #include "DLGLexer.h"
     47 
     48 class DLGLexerVfr : public DLGLexer
     49 {
     50 public:
     51   DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};
     52   INT32 errstd (char *Text)
     53   {
     54     printf ("unrecognized input '%s'\n", Text);
     55   }
     56 };
     57 
     58 //
     59 // Base token definitions for ANTLR
     60 //
     61 #include "AToken.h"
     62 
     63 //
     64 // This is how we invoke the C preprocessor on the VFR source file
     65 // to resolve #defines, #includes, etc. To make C source files
     66 // shareable between VFR and drivers, define VFRCOMPILE so that
     67 // #ifdefs can be used in shared .h files.
     68 //
     69 #define PREPROCESSOR_COMMAND        "cl.exe "
     70 #define PREPROCESSOR_OPTIONS        "/nologo /E /TC /DVFRCOMPILE "
     71 
     72 typedef ANTLRCommonToken ANTLRToken;
     73 
     74 //
     75 // Specify the filename extensions for the files we generate.
     76 //
     77 #define VFR_BINARY_FILENAME_EXTENSION       ".c"
     78 #define VFR_LIST_FILENAME_EXTENSION         ".lst"
     79 #define VFR_PREPROCESS_FILENAME_EXTENSION   ".i"
     80 
     81 static
     82 VOID
     83 Usage ();
     84 
     85 static
     86 STATUS
     87 ProcessArgs (
     88   int         Argc,
     89   char        *Argv[]
     90   );
     91 
     92 static
     93 VOID
     94 Cleanup ();
     95 
     96 //
     97 // Globals
     98 //
     99 OPTIONS gOptions;
    100 
    101 int
    102 main (
    103   int   argc,
    104   char  **argv
    105   )
    106 /*++
    107 
    108 Routine Description:
    109   Application entry point function. Parse command-line arguments,
    110   invoke the parser, clean up, and return.
    111 
    112 Arguments:
    113   argc - standard argc passed to main() per C conventions
    114   argv - standard argv passed to main() per C conventions
    115 
    116 Returns:
    117   STATUS_SUCCESS - program executed with no errors or warnings
    118   STATUS_WARNING - program executed with warnings
    119   STATUS_ERROR   - non-recoverable errors encountered while processing
    120 
    121 --*/
    122 {
    123   FILE      *VfrFptr;
    124   char      *Cmd;
    125   char      *Cptr;
    126   int       Len;
    127   STATUS    Status;
    128 
    129   //
    130   // Set our program name for the error printing routines.
    131   // Then set printing limits.
    132   //
    133   SetUtilityName (UTILITY_NAME);
    134   SetPrintLimits (20, 20, 30);
    135   //
    136   // Process the command-line arguments
    137   //
    138   if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {
    139     Usage ();
    140     Cleanup();
    141     return STATUS_ERROR;
    142   }
    143   VfrFptr = NULL;
    144   //
    145   // Verify the VFR script file exists
    146   //
    147   if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {
    148     Error (UTILITY_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");
    149     Cleanup();
    150     return STATUS_ERROR;
    151   }
    152   //
    153   // Now close the file and make a system call to run the preprocessor
    154   // on it.
    155   //
    156   fclose (VfrFptr);
    157   Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10 +
    158         strlen (PREPROCESSOR_COMMAND) + strlen (gOptions.PreprocessorOutputFileName);
    159   if (gOptions.CPreprocessorOptions != NULL) {
    160     Len += strlen (gOptions.CPreprocessorOptions) + 1;
    161   }
    162   if (gOptions.IncludePaths != NULL) {
    163     Len += strlen (gOptions.IncludePaths) + 1;
    164   }
    165   Cmd = (char *)malloc (Len);
    166   if (Cmd == NULL) {
    167     Error (UTILITY_NAME, 0, 0, NULL, "could not allocate memory");
    168     Cleanup();
    169     return STATUS_ERROR;
    170   }
    171   strcpy (Cmd, PREPROCESSOR_COMMAND PREPROCESSOR_OPTIONS);
    172   if (gOptions.IncludePaths != NULL) {
    173     strcat (Cmd, gOptions.IncludePaths);
    174     strcat (Cmd, " ");
    175   }
    176   if (gOptions.CPreprocessorOptions != NULL) {
    177     strcat (Cmd, gOptions.CPreprocessorOptions);
    178     strcat (Cmd, " ");
    179   }
    180   strcat (Cmd, gOptions.VfrFileName);
    181   strcat (Cmd, " > ");
    182   strcat (Cmd, gOptions.PreprocessorOutputFileName);
    183   Status = system (Cmd);
    184   if (Status != 0) {
    185     Error (UTILITY_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");
    186     printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);
    187     Cleanup();
    188     return STATUS_ERROR;
    189   }
    190   free (Cmd);
    191   //
    192   // Open the preprocessor output file
    193   //
    194   if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
    195     Error (UTILITY_NAME, 0, 0, "failed to open input VFR preprocessor output file",
    196       gOptions.PreprocessorOutputFileName);
    197     Cleanup();
    198     return STATUS_ERROR;
    199   }
    200   //
    201   // Define input VFR file
    202   //
    203   DLGFileInput InputFile (VfrFptr);
    204   //
    205   // Define an instance of the scanner
    206   //
    207   DLGLexerVfr Scanner (&InputFile);
    208   //
    209   // Define token buffer between scanner and parser
    210   //
    211   ANTLRTokenBuffer Pipe (&Scanner);
    212   //
    213   // Create a token to use as a model
    214   //
    215   ANTLRToken Tok;
    216   //
    217   // Tell the scanner what type the token is
    218   //
    219   Scanner.setToken (&Tok);
    220   //
    221   // Create an instance of our parser
    222   //
    223   EfiVfrParser Parser (&Pipe);
    224   //
    225   // Initialize the parser
    226   //
    227   Parser.init ();
    228   Status = GetUtilityStatus ();
    229   if (Status != STATUS_SUCCESS) {
    230     Cleanup();
    231     return Status;
    232   }
    233   //
    234   // Start the first rule
    235   //
    236   Parser.program ();
    237   //
    238   // Close the input script file
    239   //
    240   fclose (VfrFptr);
    241   Parser.WriteIfrBytes ();
    242   //
    243   // Call cleanup, which does some extra checking of the script
    244   //
    245   Parser.Cleanup ();
    246   Cleanup();
    247   //
    248   // If we had an error somewhere, delete our output files so that
    249   // a subsequent build will rebuild them.
    250   //
    251   Status = GetUtilityStatus ();
    252   if (Status == STATUS_ERROR) {
    253     remove (gOptions.IfrOutputFileName);
    254   }
    255   return Status;
    256 }
    257 static
    258 VOID
    259 Cleanup ()
    260 /*++
    261 
    262 Routine Description:
    263   Free up memory allocated during parsing.
    264 
    265 Arguments:
    266   None
    267 
    268 Returns:
    269   None
    270 
    271 --*/
    272 {
    273   //
    274   // Free up our string we allocated to track the include paths
    275   //
    276   if (gOptions.IncludePaths != NULL) {
    277     free (gOptions.IncludePaths);
    278     gOptions.IncludePaths = NULL;
    279   }
    280   //
    281   // Free up our string we allocated to track preprocessor options
    282   //
    283   if (gOptions.CPreprocessorOptions != NULL) {
    284     free (gOptions.CPreprocessorOptions);
    285     gOptions.CPreprocessorOptions = NULL;
    286   }
    287 }
    288 
    289 static
    290 STATUS
    291 ProcessArgs (
    292   int         Argc,
    293   char        *Argv[]
    294   )
    295 /*++
    296 
    297 Routine Description:
    298   Process the command-line arguments.
    299 
    300 Arguments:
    301   Argc - standard argc passed to main()
    302   Argv - standard argv passed to main()
    303 
    304 Returns:
    305   STATUS_SUCCESS - program should continue (all args ok)
    306 
    307 --*/
    308 {
    309   char    *IncludePaths;
    310   char    *CPreprocessorOptions;
    311   int     Len;
    312   char    CopyStr[MAX_PATH];
    313   char    *Cptr;
    314 
    315   //
    316   // Put options in known state.
    317   //
    318   memset ((char *)&gOptions, 0, sizeof (OPTIONS));
    319   //
    320   // Go through all the arguments that start with '-'
    321   //
    322   Argc--;
    323   Argv++;
    324   while ((Argc > 0) && (Argv[0][0] == '-')) {
    325     //
    326     // -? or -h help option -- return an error for printing usage
    327     //
    328     if ((_stricmp (Argv[0], "-?") == 0) || (_stricmp (Argv[0], "-h") == 0)) {
    329       return STATUS_ERROR;
    330       break;
    331     //
    332     // -l to create a listing output file
    333     //
    334     } else if (_stricmp (Argv[0], "-l") == 0) {
    335       gOptions.CreateListFile = 1;
    336     //
    337     // -I include_path option for finding include files. We'll pass this
    338     // to the preprocessor. Turn them all into a single include string.
    339     //
    340     } else if (_stricmp (Argv[0], "-i") == 0) {
    341       if ((Argc < 2) || (Argv[1][0] == '-')) {
    342         Error (UTILITY_NAME, 0, 0, Argv[0], "missing path argument");
    343         return STATUS_ERROR;
    344       }
    345       Argc--;
    346       Argv++;
    347       Len = strlen (" -I ");
    348       Len += strlen (Argv[0]) + 2;
    349       if (gOptions.IncludePaths != NULL) {
    350         Len += strlen (gOptions.IncludePaths);
    351       }
    352       IncludePaths = (INT8 *)malloc (Len);
    353       if (IncludePaths == NULL) {
    354         Error (UTILITY_NAME, 0, 0, NULL, "memory allocation failure");
    355         return STATUS_ERROR;
    356       }
    357       IncludePaths[0] = 0;
    358       if (gOptions.IncludePaths != NULL) {
    359         strcpy (IncludePaths, gOptions.IncludePaths);
    360         free (gOptions.IncludePaths);
    361       }
    362       strcat (IncludePaths, " -I ");
    363       strcat (IncludePaths, Argv[0]);
    364       gOptions.IncludePaths = IncludePaths;
    365     //
    366     // -od OutputDirectory to define a common directory for output files
    367     //
    368     } else if (_stricmp (Argv[0], "-od") == 0) {
    369       if ((Argc < 2) || (Argv[1][0] == '-')) {
    370         Error (UTILITY_NAME, 0, 0, Argv[0], "missing output directory name");
    371         return STATUS_ERROR;
    372       }
    373       Argc--;
    374       Argv++;
    375       strcpy (gOptions.OutputDirectory, Argv[0]);
    376     } else if (_stricmp (Argv[0], "-ibin") == 0) {
    377       gOptions.CreateIfrBinFile = 1;
    378     } else if (_stricmp (Argv[0], "-nostrings") == 0) {
    379       // deprecated option
    380     //
    381     // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
    382     // Turn them all into a single string.
    383     //
    384     } else if (_stricmp (Argv[0], "-ppflag") == 0) {
    385       if (Argc < 2) {
    386         Error (UTILITY_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
    387         return STATUS_ERROR;
    388       }
    389       Argc--;
    390       Argv++;
    391       Len = strlen (Argv[0]) + 2;
    392       if (gOptions.CPreprocessorOptions != NULL) {
    393         Len += strlen (gOptions.CPreprocessorOptions);
    394       }
    395       CPreprocessorOptions = (INT8 *)malloc (Len);
    396       if (CPreprocessorOptions == NULL) {
    397         Error (UTILITY_NAME, 0, 0, NULL, "memory allocation failure");
    398         return STATUS_ERROR;
    399       }
    400       CPreprocessorOptions[0] = 0;
    401       if (gOptions.CPreprocessorOptions != NULL) {
    402         strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
    403         free (gOptions.CPreprocessorOptions);
    404       }
    405       strcat (CPreprocessorOptions, " ");
    406       strcat (CPreprocessorOptions, Argv[0]);
    407       gOptions.CPreprocessorOptions = CPreprocessorOptions;
    408     } else {
    409       Error (UTILITY_NAME, 0, 0, Argv[0], "unrecognized option");
    410       return STATUS_ERROR;
    411     }
    412     Argc--;
    413     Argv++;
    414   }
    415   //
    416   // Must specify at least the vfr file name
    417   //
    418   if (Argc > 1) {
    419     Error (UTILITY_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
    420     return STATUS_ERROR;
    421   } else if (Argc < 1) {
    422     Error (UTILITY_NAME, 0, 0, NULL, "must specify VFR file name");
    423     return STATUS_ERROR;
    424   }
    425   strcpy (gOptions.VfrFileName, Argv[0]);
    426 
    427   strcpy (CopyStr, gOptions.VfrFileName);
    428   Cptr = CopyStr + strlen (CopyStr) - 1;
    429   for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':'); Cptr--);
    430   if (Cptr == CopyStr) {
    431     strcpy (gOptions.VfrBaseFileName, Cptr);
    432   } else {
    433     strcpy (gOptions.VfrBaseFileName, Cptr+1);
    434   }
    435   //
    436   // Terminate the vfr file basename at the extension
    437   //
    438   for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
    439   }
    440   *Cptr = 0;
    441   //
    442   // If they defined an output directory, prepend all output files
    443   // with the working directory. Output files of interest:
    444   //    VfrListFileName             -- list file
    445   //    IfrOutputFileName           -- IFR bytes
    446   //    StringOutputFileName        -- string bytes
    447   //    StringListFileName          -- not used
    448   //    StringDefineFileName        -- #defines of string identifiers
    449   //
    450   // We have two cases:
    451   //   1. Output directory (-od) not specified, in which case output files
    452   //      go to the current working directory.
    453   //   2. Output directory specified, in which case the output files
    454   //      go directly to the specified directory.
    455   //
    456   if (gOptions.OutputDirectory[0] == 0) {
    457     CopyStr[0] = 0;
    458     _getcwd (CopyStr, sizeof (CopyStr));
    459     strcpy (gOptions.OutputDirectory, CopyStr);
    460   }
    461   //
    462   // Make sure output directory has a trailing backslash
    463   //
    464   if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\') {
    465     strcat (gOptions.OutputDirectory, "\\");
    466   }
    467   //
    468   // Create the base output file name as: path\base, copy it to all the output
    469   // filenames, and then add the appropriate extension to each.
    470   //
    471   strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);
    472   strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);
    473   strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);
    474   strcpy (gOptions.PreprocessorOutputFileName, gOptions.VfrListFileName);
    475   strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);
    476   strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);
    477   strcat (gOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
    478 
    479   //
    480   // We set a default list file name, so if they do not
    481   // want a list file, null out the name now.
    482   //
    483   if (gOptions.CreateListFile == 0) {
    484     gOptions.VfrListFileName[0] = 0;
    485   }
    486   return STATUS_SUCCESS;
    487 }
    488 static
    489 VOID
    490 Usage ()
    491 /*++
    492 
    493 Routine Description:
    494   Print utility usage instructions
    495 
    496 Arguments:
    497   None
    498 
    499 Returns:
    500   None
    501 
    502 --*/
    503 {
    504   int          Index;
    505   const char   *Str[] = {
    506     UTILITY_NAME" "UTILITY_VERSION" - Intel VFR Compiler Utility",
    507     "  Copyright (C), 2004 - 2008 Intel Corporation",
    508 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
    509     "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
    510 #endif
    511     "",
    512     "Usage:",
    513     "  "UTILITY_NAME" [OPTION] VFRFILE",
    514     "Description:",
    515     "  Compile VFRFILE.",
    516     "Options:",
    517     "  -? or -h        print this help",
    518     "  -l              create an output IFR listing file",
    519     "  -i IncPath      add IncPath to the search path for VFR included files",
    520     "  -od OutputDir   deposit all output files to directory OutputDir (default=cwd)",
    521     "  -ibin           create an IFR HII pack file",
    522     "  -ppflag CFlags  pass Flags as C-preprocessor-flag",
    523     "  -v or -version  print version information",
    524     NULL
    525   };
    526 
    527   for (Index = 0; Str[Index] != NULL; Index++) {
    528     fprintf (stdout, "%s\n", Str[Index]);
    529   }
    530 }
    531 
    532 >>
    533 
    534 
    535 #lexaction
    536 <<
    537 
    538 #include "EfiVfr.h"
    539 
    540 PARSER_LINE_DEFINITION  *gLineDefinition = NULL;
    541 PARSER_LINE_DEFINITION  *gLastLineDefinition = NULL;
    542 
    543 VOID
    544 AddFileLine (
    545   char      *TokenString,
    546   UINT32    TokenLine
    547   )
    548 /*++
    549 
    550 Routine Description:
    551   During the lexer phase, if we encounter a #line statement output by
    552   the preprocessor, this function gets called. We'll save off the info
    553   for error reporting purposes. The preprocessor line information has the
    554   form:
    555 
    556     #line 3 "FileName.c"
    557 
    558 Arguments:
    559   TokenString - the parsed string as shown above
    560   TokenLine   - the line number in the preprocessed output file
    561 
    562 Returns:
    563   NA
    564 
    565 --*/
    566 {
    567   PARSER_LINE_DEFINITION  *LineDef;
    568   INT8                    *Cptr;
    569 
    570   //
    571   // Allocate a structure in which we can keep track of this line information.
    572   //
    573   LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));
    574   memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));
    575   LineDef->TokenLineNum = TokenLine;
    576   LineDef->HashLineNum = atoi (TokenString + 6);
    577   //
    578   // Find the quotes in the filename, then allocate space in the line
    579   // def structure for a copy of the filename. Finally, copy it without
    580   // quotes to the line def.
    581   //
    582   for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
    583   if (*Cptr == '"') {
    584     LineDef->FileName = (INT8 *)malloc (strlen (Cptr));
    585     Cptr++;
    586     strcpy (LineDef->FileName, Cptr);
    587     for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
    588     *Cptr = 0;
    589     //
    590     // Now add this new one to the list
    591     //
    592     if (gLineDefinition == NULL) {
    593       gLineDefinition = LineDef;
    594     } else {
    595       gLastLineDefinition->Next = LineDef;
    596     }
    597     gLastLineDefinition = LineDef;
    598   } else {
    599     Error (UTILITY_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
    600     free (LineDef);
    601     return;
    602   }
    603 }
    604 char *
    605 ConvertLineNumber (
    606   UINT32 *LineNum
    607   )
    608 /*++
    609 
    610 Routine Description:
    611   Given the line number in the preprocessor-output file, use the line number
    612   information we've saved to determine the source file name and line number
    613   where the code originally came from. This is required for error reporting.
    614 
    615 Arguments:
    616   LineNum - the line number in the preprocessor-output file.
    617 
    618 Returns:
    619   Returns a pointer to the source file name. Also returns the line number
    620   in the provided LineNum argument
    621 
    622 --*/
    623 {
    624   PARSER_LINE_DEFINITION  *LineDef;
    625   //
    626   // Step through our linked list of #line information we saved off.
    627   // For each one, look at its line number, and the line number of the
    628   // next record, and see if the passed-in line number is in the range.
    629   // If it is, then convert the line number to the appropriate line number
    630   // of the original source file.
    631   //
    632   for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
    633     //
    634     // The given LineNum is the line number from the .i file.
    635     // Find a line definition whose range includes this line number,
    636     // convert the line number, and return the filename.
    637     //
    638     if (LineDef->TokenLineNum <= *LineNum) {
    639       if (LineDef->Next != NULL) {
    640         if (LineDef->Next->TokenLineNum > *LineNum) {
    641           *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
    642           return LineDef->FileName;
    643         }
    644       } else {
    645         //
    646         // Last one in the list of line definitions, so has to be right
    647         //
    648         *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
    649         return LineDef->FileName;
    650       }
    651     }
    652   }
    653   return NULL;
    654 }
    655 
    656 >>
    657 
    658 //
    659 // Define a lexical class for parsing quoted strings. Basically
    660 // starts with a double quote, and ends with a double quote that
    661 // is not preceeded with a backslash.
    662 //
    663 #lexclass QUOTED_STRING
    664 #token TheString            "~[\"]*\"" << mode (START); >>
    665 
    666 //
    667 // Define a lexical class for parsing "#pragma pack" statements.
    668 // We do this just for convenience (since we skip them here) so
    669 // that users can include some minimal .h files.
    670 //
    671 #lexclass PRAGMA_PACK
    672 #token "pack"     << skip (); >>
    673 #token "[\ \t]"   << skip (); >>
    674 #token "\("       << skip (); >>
    675 #token "[0-9]*"   << skip (); >>
    676 #token "\)"       << skip (); mode (START); >>
    677 
    678 //
    679 // Define a lexclass for skipping over C++ style comments
    680 //
    681 #lexclass CPP_COMMENT
    682 #token "~[\n]*"       << skip (); >>
    683 #token "\n"           << skip (); mode (START); newline (); >>
    684 
    685 //
    686 // Standard lexclass is START
    687 //
    688 #lexclass START
    689 
    690 //
    691 // Find start of C++ style comments
    692 //
    693 #token "//"     << skip (); mode (CPP_COMMENT); >>
    694 
    695 //
    696 // Skip whitespace
    697 //
    698 #token "[\ \t]"   << skip (); >>
    699 
    700 //
    701 // Skip over newlines, but count them
    702 //
    703 #token "\n"       << skip (); newline (); >>
    704 
    705 //
    706 // Skip pragma pack statements
    707 //
    708 #token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
    709 
    710 //
    711 // Skip over 'extern' in any included .H file
    712 //
    713 #token "extern"   << skip (); >>
    714 
    715 //
    716 // Tokens for the different keywords. Syntax is:
    717 // TokenName("ErrorMessageText")    "TokenString"
    718 //   where:
    719 //     TokenName is the token name (must be capitalized) that is used in the rules
    720 //     ErrorMessageText is the string the compiler emits when it detects a syntax error
    721 //     TokenString is the actual matching string used in the user script
    722 //
    723 #token LineDefinition                           "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>
    724 #token FormSet("formset")                       "formset"
    725 #token EndFormSet("endformset")                 "endformset"
    726 #token Title("title")                           "title"
    727 #token FormId("formid")                         "formid"
    728 #token OneOf("oneof")                           "oneof"
    729 #token Prompt("prompt")                         "prompt"
    730 #token OrderedList("orderedlist")               "orderedlist"
    731 #token EndList("endlist")                       "endlist"
    732 #token EndForm("endform")                       "endform"
    733 #token EndOneOf("endoneof")                     "endoneof"
    734 #token Form("form")                             "form"
    735 #token Subtitle("subtitle")                     "subtitle"
    736 #token Help("help")                             "help"
    737 #token VarId("varid")                           "varid"
    738 #token Text("text")                             "text"
    739 #token Option("option")                         "option"
    740 #token Value("value")                           "value"
    741 #token Flags("flags")                           "flags"
    742 #token Date("date")                             "date"
    743 #token EndDate("enddate")                       "enddate"
    744 #token Year("year")                             "year"
    745 #token Month("month")                           "month"
    746 #token Day("day")                               "day"
    747 #token Time("time")                             "time"
    748 #token EndTime("endtime")                       "endtime"
    749 #token Hour("hour")                             "hour"
    750 #token Minute("minute")                         "minute"
    751 #token Second("second")                         "second"
    752 #token AND("AND")                               "AND"
    753 #token OR("OR")                                 "OR"
    754 #token GrayOutIf("grayoutif")                   "grayoutif"
    755 #token NOT("NOT")                               "NOT"
    756 #token Label("label")                           "label"
    757 #token Timeout("timeout")                       "timeout"
    758 #token Inventory("inventory")                   "inventory"
    759 #token StringToken("STRING_TOKEN")              "STRING_TOKEN"
    760 #token NonNvDataMap("_NON_NV_DATA_MAP")         "_NON_NV_DATA_MAP"
    761 #token Struct("struct")                         "struct"
    762 #token Uint64("UINT64")                         "UINT64"
    763 #token Uint32("UINT32")                         "UINT32"
    764 #token Uint16("UINT16")                         "UINT16"
    765 #token Char16("CHAR16")                         "CHAR16"
    766 #token Uint8("UINT8")                           "UINT8"
    767 #token Guid("guid")                             "guid"
    768 #token CheckBox("checkbox")                     "checkbox"
    769 #token EndCheckBox("endcheckbox")               "endcheckbox"
    770 #token Numeric("numeric")                       "numeric"
    771 #token EndNumeric("endnumeric")                 "endnumeric"
    772 #token Minimum("minimum")                       "minimum"
    773 #token Maximum("maximum")                       "maximum"
    774 #token Step("step")                             "step"
    775 #token Default("default")                       "default"
    776 #token Password("password")                     "password"
    777 #token EndPassword("endpassword")               "endpassword"
    778 #token String("string")                         "string"
    779 #token EndString("endstring")                   "endstring"
    780 #token MinSize("minsize")                       "minsize"
    781 #token MaxSize("maxsize")                       "maxsize"
    782 #token Encoding("encoding")                     "encoding"
    783 #token SuppressIf("suppressif")                 "suppressif"
    784 #token Hidden("hidden")                         "hidden"
    785 #token Goto("goto")                             "goto"
    786 #token InconsistentIf                           "inconsistentif"
    787 #token EndIf("endif")                           "endif"
    788 #token IdEqId("ideqid")                         "ideqid"
    789 #token IdEqVal("ideqval")                       "ideqval"
    790 #token VarEqVal("vareqval")                     "vareqval"
    791 #token Var("var")                               "var"
    792 #token IdEqValList("ideqvallist")               "ideqvallist"
    793 #token Length("length")                         "length"
    794 #token Values("values")                         "values"
    795 #token Key("key")                               "key"
    796 #token DefaultFlag("DEFAULT")                   "DEFAULT"
    797 #token ManufacturingFlag("MANUFACTURING")       "MANUFACTURING"
    798 #token InteractiveFlag("INTERACTIVE")           "INTERACTIVE"
    799 #token NVAccessFlag("NV_ACCESS")                "NV_ACCESS"
    800 #token ResetRequiredFlag("RESET_REQUIRED")      "RESET_REQUIRED"
    801 #token LateCheckFlag("LATE_CHECK")              "LATE_CHECK"
    802 #token Class("class")                           "class"
    803 #token Subclass("subclass")                     "subclass"
    804 #token TypeDef("typedef")                       "typedef"
    805 #token Restore("restore")                       "restore"
    806 #token Save("save")                             "save"
    807 #token Defaults("defaults")                     "defaults"
    808 #token Banner("banner")                         "banner"
    809 #token Align("align")                           "align"
    810 #token Left("left")                             "left"
    811 #token Right("right")                           "right"
    812 #token Center("center")                         "center"
    813 #token Line("line")                             "line"
    814 #token VarStore("varstore")                     "varstore"
    815 #token Name("name")                             "name"
    816 #token Oem("oem")                               "oem"
    817 #token True("TRUE")                             "TRUE"
    818 #token False("FALSE")                           "FALSE"
    819 #token GreaterThan(">")                         ">"
    820 #token GreaterEqual(">=")                       ">="
    821 #token LessThan("<")                          "<"
    822 #token LessEqual("<=")                        "<="
    823 
    824 //
    825 // Define the class and subclass tokens
    826 //
    827 #token ClassNonDevice("NONDEVICE")                        "NON_DEVICE"
    828 #token ClassDiskDevice("DISK_DEVICE")                     "DISK_DEVICE"
    829 #token ClassVideoDevice("VIDEO_DEVICE")                   "VIDEO_DEVICE"
    830 #token ClassNetworkDevice("NETWORK_DEVICE")               "NETWORK_DEVICE"
    831 #token ClassInputDevice("INPUT_DEVICE")                   "INPUT_DEVICE"
    832 #token ClassOnBoardDevice("ONBOARD_DEVICE")               "ONBOARD_DEVICE"
    833 #token ClassOtherDevice("OTHER_DEVICE")                   "OTHER_DEVICE"
    834 
    835 #token SubclassSetupApplication("SETUP_APPLICATION")      "SETUP_APPLICATION"
    836 #token SubclassGeneralApplication("GENERAL_APPLICATION")  "GENERAL_APPLICATION"
    837 #token SubclassFrontPage("FRONT_PAGE")                    "FRONT_PAGE"
    838 #token SubclassSingleUse("SINGLE_USE")                    "SINGLE_USE"
    839 
    840 #token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]"   // 3 lowercase characters
    841 #token StringIdentifier("string identifier")    "[A-Za-z_][A-Za-z_0-9]*"
    842 #token Number("numeric value")                  "(0x[0-9A-Fa-f]+) | [0-9]+"
    843 #token OpenBrace("{")                           "\{"
    844 #token CloseBrace("}")                          "\}"
    845 #token OpenParen("(")                           "\("
    846 #token CloseParen(")")                          "\)"
    847 #token OpenBracket("[")                         "\["
    848 #token CloseBracket("]")                        "\]"
    849 
    850 //
    851 // Define all other invalid characters so that they get through the lexical phase
    852 // and we can catch them during the parse phase. We get much better error
    853 // messages then.
    854 //
    855 #token InvalidCharacters("invalid characters")  "~[;:=,\.\|]"
    856 
    857 //
    858 // This is the overall definition of a VFR form definition script.
    859 //
    860 program :
    861   ( dataStructDefinition )*
    862   formSetStatement
    863   ( vfrStatementVarStore )*
    864   ( formDefinition )*
    865   EFS:EndFormSet  ";"                   << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>
    866   "@" // end of file
    867   ;
    868 
    869 formSetStatement :
    870   FS:FormSet                            << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>
    871   Guid "="
    872   OpenBrace
    873   G1:Number ","
    874   G2:Number ","
    875   G3:Number ","
    876   G4:Number ","
    877   G5:Number ","
    878   G6:Number ","
    879   G7:Number ","
    880   G8:Number ","
    881   G9:Number ","
    882   G10:Number ","
    883   G11:Number
    884   CloseBrace                            << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
    885                                                            G4->getText (), G5->getText (), G6->getText (), G7->getText (),
    886                                                            G8->getText (), G9->getText (), G10->getText (), G11->getText ()
    887                                                           );
    888                                          >>
    889   ","
    890   Title "=" getStringId ","
    891   Help  "=" getStringId ","
    892   //
    893   // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)
    894   //
    895                                             << WriteDWord (0, 0); WriteDWord (0, 0); >>
    896   Class "=" CVAL:classDefinition ","        << WriteClass (); >>
    897   Subclass "=" SVAL:subclassDefinition ","  << WriteSubclass (); >>
    898                                             << WriteWord (mNvDataStructSize); >>
    899   ;
    900 
    901 //
    902 // A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C
    903 //
    904 classDefinition :
    905   validClassNames ( "\|" validClassNames )*
    906   ;
    907 
    908 validClassNames :
    909     CND:ClassNonDevice          << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>
    910   | CDD:ClassDiskDevice         << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>
    911   | CVD:ClassVideoDevice        << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>
    912   | CNW:ClassNetworkDevice      << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>
    913   | CID:ClassInputDevice        << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>
    914   | COB:ClassOnBoardDevice      << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>
    915   | COD:ClassOtherDevice        << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>
    916   | CNUM:Number                 << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>
    917   ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>
    918 
    919 //
    920 // A form can only be of one subclass type.
    921 //
    922 subclassDefinition :
    923     SSA:SubclassSetupApplication    << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>
    924   | SGA:SubclassGeneralApplication  << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>
    925   | SFP:SubclassFrontPage           << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>
    926   | SSU:SubclassSingleUse           << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>
    927   | SNUM:Number                     << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>
    928   ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>
    929 
    930 //
    931 // Parse a C type data structure for storing VFR setup data. Allow:
    932 //  typedef struct _XXX_ {
    933 //     (fields)
    934 //  } MY_NV_DATA;
    935 //
    936 dataStructDefinition :
    937   << int IsNonNV = 0; >>
    938   { TypeDef }
    939   S:Struct
    940   (
    941     NonNvDataMap                    << IsNonNV = 1; >>
    942   |
    943     { StringIdentifier }
    944   )                                 << StartStructDefinition (IsNonNV, S->getLine()); >>
    945   OpenBrace
    946   dataStructFields
    947   CloseBrace NAME:StringIdentifier  << EndStructDefinition (NAME->getText(), NAME->getLine()); >>
    948   ";"
    949   ;
    950 
    951 dataStructFields :
    952   ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *
    953   ;
    954 
    955 //*****************************************************************************
    956 //
    957 // PARSE:
    958 //   UINT64 Name[4];
    959 //   UINT64 Name;
    960 //
    961 // Used while parsing the NV data map structures.
    962 //
    963 dataStructField64 :
    964   << int ArrayLength = 1; char IsArray = 0; >>
    965   "UINT64"
    966   NAME:StringIdentifier
    967   ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
    968                                                     << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>
    969   ;
    970 
    971 //*****************************************************************************
    972 //
    973 // PARSE:
    974 //   UINT32 Name[4];
    975 //   UINT32 Name;
    976 //
    977 // Used while parsing the NV data map structures.
    978 //
    979 dataStructField32 :
    980   << int ArrayLength = 1; char IsArray = 0; >>
    981   "UINT32"
    982   NAME:StringIdentifier
    983   ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
    984                                                     << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>
    985   ;
    986 
    987 //*****************************************************************************
    988 //
    989 // PARSE:
    990 //   UINT16 Name[4];
    991 //   UINT16 Name;
    992 //
    993 // Used while parsing the NV data map structures.
    994 //
    995 dataStructField16 :
    996   << int ArrayLength = 1; char IsArray = 0; >>
    997   ( "UINT16" | "CHAR16" )
    998   NAME:StringIdentifier
    999   ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
   1000                                                     << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>
   1001   ;
   1002 
   1003 //*****************************************************************************
   1004 //
   1005 // PARSE:
   1006 //   UINT8 Name[4];
   1007 //   UINT8 Name;
   1008 //
   1009 // Used while parsing the NV data map structures.
   1010 //
   1011 dataStructField8 :
   1012   << int ArrayLength = 1; char IsArray = 0; >>
   1013   "UINT8"
   1014   NAME:StringIdentifier
   1015   ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
   1016                                                     << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>
   1017   ;
   1018 
   1019 //*****************************************************************************
   1020 //
   1021 // PARSE:
   1022 //    form formid = 1,
   1023 //      title  = STRING_TOKEN(STR_FORM_TITLE);
   1024 //      -- form statements --
   1025 //    endform;
   1026 //
   1027 //  The Form ID cannot be 0
   1028 //
   1029 formDefinition :
   1030   FRM:Form FormId                << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >>
   1031   "="
   1032   VAL:Number                     << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>
   1033   ","
   1034   Title "=" getStringId ";"      // writes string identifier
   1035   ( vfrStatements )*
   1036   ENDF:EndForm  ";"              << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>
   1037   ;
   1038 
   1039 //
   1040 // VFR statements in a formset
   1041 //
   1042 vfrStatements :
   1043   vfrStatementSubTitle        |
   1044   vfrStatementOneOf           |
   1045   vfrStatementTextText        |
   1046   vfrStatementCheckBox        |
   1047   vfrStatementNumeric         |
   1048   vfrStatementDate            |
   1049   vfrStatementTime            |
   1050   vfrStatementPassword        |
   1051   vfrStatementString          |
   1052   vfrStatementSuppressIf      |
   1053   vfrStatementHidden          |
   1054   vfrStatementGoto            |
   1055   vfrStatementGrayOutIf       |
   1056   vfrStatementInconsistentIf  |
   1057   vfrStatementLabel           |
   1058   vfrStatementBanner          |
   1059   vfrStatementInventory       |
   1060   vfrStatementOrderedList     |
   1061   vfrStatementOem             |
   1062   vfrStatementSaveRestoreDefaults
   1063   ;
   1064 
   1065 //*****************************************************************************
   1066 //
   1067 // PARSE:
   1068 //   label 100;
   1069 //
   1070 vfrStatementLabel :
   1071   OPID:Label                              << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>
   1072   VAL:Number                              <<
   1073                                               WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
   1074                                               AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
   1075                                           >>
   1076   ";"
   1077   ;
   1078 
   1079 //*****************************************************************************
   1080 //
   1081 // PARSE:
   1082 //   oem 0x12, 0x34, 0x56;
   1083 //
   1084 vfrStatementOem :
   1085   OPID:Oem                              << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>
   1086   ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )
   1087   ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*
   1088   ";"
   1089   ;
   1090 
   1091 //*****************************************************************************
   1092 //
   1093 // PARSE:
   1094 //   inconsistentif NOT .... AND NOT .... OR ... endif;
   1095 //
   1096 vfrStatementInconsistentIf :
   1097   << ResetFlags (); >>
   1098   IIFOP:InconsistentIf                  << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>
   1099   Prompt "=" getStringId ","
   1100   {
   1101     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1102   }
   1103   << WriteFlags (); >> //  write the flags field
   1104   vfrBooleanExpression
   1105   EOP:EndIf ";"                         << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>
   1106   ;
   1107 
   1108 //*****************************************************************************
   1109 //
   1110 // PARSE:
   1111 //   TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR
   1112 //               ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND
   1113 //            (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR
   1114 //               vareqval var(VAR_EQ_TEST_NAME) == 0x1)
   1115 //
   1116 // For supporting complex express, divide the vfrBooleanExpression to two parts
   1117 // so that pred-LL(k) parser can parse incrementally.
   1118 //
   1119 vfrBooleanExpression :
   1120   leftPartVfrBooleanExp { rightPartVfrBooleanExp }
   1121   ;
   1122 
   1123 leftPartVfrBooleanExp :
   1124   OpenParen vfrBooleanExpression CloseParen                                                        |
   1125   (ideqval | ideqid | ideqvallist | vareqval | truefalse)                                          |
   1126   NOPID:NOT leftPartVfrBooleanExp           << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
   1127   ;
   1128 
   1129 rightPartVfrBooleanExp :
   1130   AOPID:AND vfrBooleanExpression            << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >>  |
   1131   OOPID:OR vfrBooleanExpression             << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>
   1132   ;
   1133 
   1134 //*****************************************************************************
   1135 //
   1136 // PARSE:
   1137 //   TRUE
   1138 //
   1139 truefalse :
   1140   TOPID:True                                << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |
   1141   FOPID:False                               << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>
   1142   ;
   1143 
   1144 //*****************************************************************************
   1145 //
   1146 // PARSE:
   1147 //   varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};
   1148 //
   1149 vfrStatementVarStore :
   1150   OP:VarStore                           << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>
   1151   STRUCT_NAME:StringIdentifier ","
   1152   Key   "=" KNUM:Number ","
   1153   Name  "=" VAR_NAME:StringIdentifier ","
   1154   Guid "="
   1155   OpenBrace
   1156   G1:Number ","
   1157   G2:Number ","
   1158   G3:Number ","
   1159   G4:Number ","
   1160   G5:Number ","
   1161   G6:Number ","
   1162   G7:Number ","
   1163   G8:Number ","
   1164   G9:Number ","
   1165   G10:Number ","
   1166   G11:Number
   1167   CloseBrace                            << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
   1168                                                            G4->getText (), G5->getText (), G6->getText (), G7->getText (),
   1169                                                            G8->getText (), G9->getText (), G10->getText (), G11->getText ()
   1170                                                           );
   1171                                            WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2));
   1172                                            AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());
   1173                                          >>
   1174 
   1175   ";"
   1176   ;
   1177 
   1178 //*****************************************************************************
   1179 //
   1180 // PARSE:
   1181 //   vareqval var(0x100) == 0x20
   1182 //
   1183 vareqval :
   1184   OPID:VarEqVal                           << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>
   1185   Var OpenParen
   1186   VAR:Number                              << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>
   1187   CloseParen
   1188   compareNumber
   1189   ;
   1190 
   1191 ideqval :
   1192   OPID:IdEqVal                            << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>
   1193   vfrStructFieldName[0]
   1194   compareNumber
   1195   ;
   1196 
   1197 //*****************************************************************************
   1198 //
   1199 // PARSE:
   1200 //   ideqid MyNVData3.Field16A == MyNVData3.Field16B
   1201 //
   1202 // NOTE: Before processing the second variable store in the ideqid statement, set a global flag
   1203 //       so that when we parse the second variable we set the secondary variable store id.
   1204 //
   1205 ideqid :
   1206   OPID:IdEqId                             << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP);  >>
   1207   vfrStructFieldName[0]
   1208   compareVfrStructFieldNameNL0
   1209   ;
   1210 
   1211 //*****************************************************************************
   1212 //
   1213 // compareNumber is the combination of compare operation and Number
   1214 //
   1215 compareNumber :
   1216   (
   1217   "=="
   1218   VAL1:Number                             << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>
   1219   ) |
   1220   (
   1221   GTOPID:GreaterThan
   1222   VAL2:Number                             << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));
   1223                                              WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
   1224   ) |
   1225   (
   1226   GEOPID:GreaterEqual
   1227   VAL3:Number                             << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));
   1228                                              WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
   1229   ) |
   1230   (
   1231   LTOPID:LessThan
   1232   VAL4:Number                             << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));
   1233                                              WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
   1234                                              WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
   1235   ) |
   1236   (
   1237   LEOPID:LessEqual
   1238   VAL5:Number                             << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));
   1239                                              WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
   1240                                              WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
   1241   )
   1242   ;
   1243 
   1244 //*****************************************************************************
   1245 //
   1246 // compareVfrStructFieldNameNL0 is the combination of compare operation and  vfrStructFieldNameNL[0]
   1247 //
   1248 compareVfrStructFieldNameNL0 :
   1249   (
   1250   "=="                                    << mIdEqIdStmt = 1; >>
   1251   vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0; >>
   1252   ) |
   1253   (
   1254   GTOPID:GreaterThan                      << mIdEqIdStmt = 1; >>
   1255   vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;
   1256                                              WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
   1257   ) |
   1258   (
   1259   GEOPID:GreaterEqual                     << mIdEqIdStmt = 1; >>
   1260   vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;
   1261                                              WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
   1262   ) |
   1263   (
   1264   LTOPID:LessThan                       << mIdEqIdStmt = 1; >>
   1265   vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;
   1266                                              WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
   1267                                              WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
   1268   ) |
   1269   (
   1270   LEOPID:LessEqual                      << mIdEqIdStmt = 1; >>
   1271   vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;
   1272                                              WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
   1273                                              WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
   1274   )
   1275   ;
   1276 
   1277 
   1278 ideqvallist :
   1279   OPID:IdEqValList                        << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>
   1280   vfrStructFieldName[0]
   1281   "=="
   1282   ( VAL:Number                            << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +
   1283                                           << FlushQueueIdEqValList(); >>
   1284   ;
   1285 
   1286 vfrStatementGoto :
   1287   << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
   1288   IDG:Goto                          << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>
   1289   VAL:Number  ","                   << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
   1290                                        AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
   1291                                     >>
   1292   KP:Prompt   "=" getStringId ","   << LineNum = KP->getLine();  >>
   1293   Help        "=" getStringId
   1294   {
   1295     ","
   1296     FF:Flags  "=" flagsField ( "\|" flagsField )*  << LineNum = FF->getLine(); >>
   1297   }
   1298   {
   1299     "," Key   "=" KNUM:Number       << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
   1300   }
   1301                                     << WriteFlagsKey (KeyValue, LineNum); >>
   1302   ";"
   1303   ;
   1304 
   1305 vfrStatementHidden :
   1306   IDH:Hidden                  << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>
   1307   Value "="
   1308   VAL:Number ","              << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>
   1309   Key "="
   1310   KVAL:Number                 << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>
   1311   ";"
   1312   ;
   1313 
   1314 //*****************************************************************************
   1315 //
   1316 // PARSE:
   1317 //   suppressif <boolean_expression> { grayoutif } <statements>+ endif;
   1318 // Note:
   1319 //   You can have: suppressif:grayoutif:statements:endif
   1320 //                 suppressif:grayoutif:endif                  -- serves no purpose
   1321 //                 suppressif:statements:endif
   1322 //                 suppressif:endif                            -- serves no purpose
   1323 //
   1324 vfrStatementSuppressIf :
   1325   << ResetFlags (); >>
   1326   OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
   1327   {
   1328     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1329   }
   1330   << WriteFlags (); >> //  write the flags field
   1331   vfrBooleanExpression
   1332   ";"
   1333   { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+
   1334   ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
   1335   ;
   1336 
   1337 //
   1338 // This is the form for a grayoutif nested in a suppressif statement
   1339 //
   1340 suppressIfGrayOutIf :
   1341   << ResetFlags (); >>
   1342   OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>
   1343   {
   1344     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1345   }
   1346   << WriteFlags (); >> //  write the flags field
   1347   vfrBooleanExpression
   1348   ";"
   1349   ;
   1350 
   1351 //*****************************************************************************
   1352 //
   1353 // PARSE:
   1354 //   grayoutif { flags = n, } <boolean_expression> endif;
   1355 // Note:
   1356 //   You can have: grayoutif:suppressif:statements:endif
   1357 //                 grayoutif:statements:endif
   1358 //
   1359 //
   1360 vfrStatementGrayOutIf :
   1361   << ResetFlags (); >>
   1362   OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
   1363   {
   1364     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1365   }
   1366   << WriteFlags (); >> //  write the flags field
   1367   vfrBooleanExpression
   1368   ";"
   1369   { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+
   1370   ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
   1371   ;
   1372 
   1373 //
   1374 // This is the format for a suppressif nested in a grayoutif
   1375 //
   1376 grayoutIfSuppressIf :
   1377   << ResetFlags (); >>
   1378   OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>
   1379   {
   1380     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1381   }
   1382   << WriteFlags (); >> //  write the flags field
   1383   vfrBooleanExpression
   1384   ";"
   1385   ;
   1386 
   1387 //
   1388 // These are the VFR statements that are valid inside a suppressif or grayoutif statement.
   1389 //
   1390 suppressIfAndGrayoutIfSubstatements :
   1391   vfrStatementOneOf           |
   1392   vfrStatementTextText        |
   1393   vfrStatementCheckBox        |
   1394   vfrStatementNumeric         |
   1395   vfrStatementDate            |
   1396   vfrStatementTime            |
   1397   vfrStatementPassword        |
   1398   vfrStatementString          |
   1399   vfrStatementHidden          |
   1400   vfrStatementGoto            |
   1401   vfrStatementLabel           |
   1402   vfrStatementInventory       |
   1403   vfrStatementOrderedList     |
   1404   vfrStatementSaveRestoreDefaults
   1405   ;
   1406 
   1407 //*****************************************************************************
   1408 //
   1409 // PARSE:
   1410 //
   1411 //    password  varid    = MyNvData.Password,
   1412 //              prompt   = STRING_TOKEN(STR_PASSWORD_PROMPT),
   1413 //              help     = STRING_TOKEN(STR_PASSWORD_HELP),
   1414 //              minsize  = 6,
   1415 //              maxsize  = 20,
   1416 //              encoding = 1,
   1417 //    endpassword;
   1418 
   1419 vfrStatementPassword :
   1420   << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
   1421   IDPW:Password                       << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>
   1422   VarId       "=" vfrStructFieldNameArray[0] ","
   1423   Prompt      "=" getStringId ","
   1424   KH:Help     "=" getStringId ","    << LineNum = KH->getLine(); >>
   1425   {
   1426     FF:Flags  "=" flagsField ( "\|" flagsField )* ","  << LineNum = FF->getLine(); >>
   1427   }
   1428   {
   1429     Key "=" KNUM:Number ","           << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
   1430   }
   1431                                       << WriteFlagsKey (KeyValue, LineNum); >>
   1432   MinSize   "=" MIN:Number ","        << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
   1433   MaxSize   "=" MAX:Number ","        << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
   1434   Encoding  "=" ENC:Number ","        << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>
   1435   EndPassword  ";"
   1436   ;
   1437 
   1438 //*****************************************************************************
   1439 //
   1440 //  PARSE:
   1441 //
   1442 //    string    varid    = MyNv.String,
   1443 //              prompt   = STRING_TOKEN(STR_STRING_PROMPT),
   1444 //              help     = STRING_TOKEN(STR_STRING_HELP),
   1445 //              flags    = INTERACTIVE,
   1446 //              key      = 0x1234,
   1447 //              minsize  = 6,
   1448 //              maxsize  = 0x14,
   1449 //    endstring;
   1450 //
   1451 // Since flags and key are optional, we can't use Flags->getLine(). Therefore for error
   1452 // reporting we save the line number of the "help" keyword.
   1453 //
   1454 vfrStatementString :
   1455   << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
   1456   IDS:String                                << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>
   1457   VarId     "=" vfrStructFieldNameArray[0] ","
   1458   Prompt    "=" getStringId ","
   1459   KH:Help   "=" getStringId ","             << LineNum = KH->getLine(); >>
   1460   {
   1461     FF:Flags "="
   1462     flagsField ( "\|" flagsField )*         << LineNum = FF->getLine(); >>
   1463     ","
   1464   }
   1465   {
   1466     Key "=" KNUM:Number ","                 << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
   1467   }
   1468                                             << WriteFlagsKey (KeyValue, LineNum); >>
   1469   MinSize   "=" MIN:Number ","              << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0);  >>
   1470   MaxSize   "=" MAX:Number ","              << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
   1471   EndString  ";"
   1472   ;
   1473 
   1474 //*****************************************************************************
   1475 //
   1476 // PARSE:
   1477 //    numeric varid   = MyIfrNVData.HowOldAreYouInYears,
   1478 //            prompt  = STRING_TOKEN(STR_NUMERIC_PROMPT),
   1479 //            help    = STRING_TOKEN(STR_NUMERIC_HELP),
   1480 //            flags   = INTERACTIVE,  // flags is optional
   1481 //            key     = 0x1234,       // key is optional if (flags & INTERACTIVE = 0)
   1482 //            minimum = 0x0,
   1483 //            maximum = 0xf0,
   1484 //            step    = 1,            // step is option, and step=1 if not specified
   1485 //            default = 0;            // default is optional, and default=minimum if not specified
   1486 //    endnumeric;
   1487 //
   1488 // Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.
   1489 // That check is done in WriteFlagsKey() function.
   1490 //
   1491 vfrStatementNumeric :
   1492   << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
   1493   IDN:Numeric                         << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>
   1494   VarId     "=" vfrStructFieldName[2] ","
   1495   Prompt    "=" getStringId ","
   1496   KH:Help   "=" getStringId ","       << LineNum = KH->getLine(); >>
   1497   {
   1498     FF:Flags "=" flagsField ( "\|" flagsField )* ","     << LineNum = FF->getLine (); >>
   1499   }
   1500   {
   1501     Key "=" KNUM:Number  ","          << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
   1502   }
   1503                                       << WriteFlagsKey (KeyValue, LineNum); >>
   1504   minMaxStepDefault
   1505   EndNumeric ";"                      << WriteMinMaxStepDefault (); >>
   1506   ;
   1507 
   1508 //
   1509 // Parse minimum/maximum/step/default statements. Special cases:
   1510 //   - if step not specified, then the value is 1
   1511 //   - if default not specified, then the value is the min value specified
   1512 //   - if max < min, print a warning and swap the values (changes default too)
   1513 //
   1514 minMaxStepDefault :
   1515   << InitMinMaxStepDefault (); >>
   1516   Minimum   "=" MIN:Number ","        << SetMinMaxStepDefault (GetNumber (MIN->getText(),  MIN->getLine(), 2), 0, MIN->getLine()); >>
   1517   Maximum   "=" MAX:Number ","        << SetMinMaxStepDefault (GetNumber (MAX->getText(),  MAX->getLine(), 2), 1, MAX->getLine()); >>
   1518   { Step    "=" STEP:Number ","       << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }
   1519   { Default "=" DEF:Number ","        << SetMinMaxStepDefault (GetNumber (DEF->getText(),  DEF->getLine(), 2), 3, DEF->getLine()); >> }
   1520   ;
   1521 
   1522 
   1523 //*****************************************************************************
   1524 //
   1525 // PARSE:
   1526 //
   1527 //    date    year varid  = Date.Year,                        // "Date.Year" is a special case we recognize
   1528 //            prompt      = STRING_TOKEN(STR_DATE_PROMPT),
   1529 //            help        = STRING_TOKEN(STR_DATE_YEAR_HELP),
   1530 //            minimum     = 1939,
   1531 //            maximum     = 2101,
   1532 //            step        = 1,
   1533 //            default     = 1964,
   1534 //
   1535 //            month varid = Date.Month,
   1536 //            prompt      = STRING_TOKEN(STR_DATE_PROMPT),
   1537 //            help        = STRING_TOKEN(STR_DATE_MONTH_HELP),
   1538 //            minimum     = 1,
   1539 //            maximum     = 12,
   1540 //            step        = 1,
   1541 //            default     = 1,
   1542 //
   1543 //            day varid   = Date.Day,
   1544 //            prompt      = STRING_TOKEN(STR_DATE_PROMPT),
   1545 //            help        = STRING_TOKEN(STR_DATE_DAY_HELP),
   1546 //            minimum     = 1,
   1547 //            maximum     = 31,
   1548 //            step        = 0x1,
   1549 //            default     = 1,
   1550 //
   1551 //    enddate;
   1552 //
   1553 vfrStatementDate :
   1554   Date
   1555   IDY:Year VarId "="                  << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>
   1556   vfrStructFieldName[2] ","
   1557   dateTimeSubStatement
   1558   IDM:Month VarId "="                 << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>
   1559   vfrStructFieldName[2] ","
   1560   dateTimeSubStatement
   1561   IDD:Day VarId "="                   << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >>
   1562   vfrStructFieldName[2] ","
   1563   dateTimeSubStatement
   1564   EndDate ";"
   1565   ;
   1566 
   1567 vfrStatementTime :
   1568   Time
   1569   IDH:Hour VarId "="                  << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>
   1570   vfrStructFieldName[2] ","
   1571   dateTimeSubStatement
   1572   IDM:Minute VarId "="                << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>
   1573   vfrStructFieldName[2] ","
   1574   dateTimeSubStatement
   1575   IDS:Second VarId "="                << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>
   1576   vfrStructFieldName[2] ","
   1577   dateTimeSubStatement
   1578   EndTime ";"
   1579   ;
   1580 
   1581 //*****************************************************************************
   1582 //
   1583 // PARSE:
   1584 //
   1585 //   text  text = STRING_ID;
   1586 //   text  text = STRING_ID, text = STRING_ID;
   1587 //   text  text = STRING_ID, text = STRING_ID, flags = x, key = y;
   1588 //
   1589 vfrStatementTextText :
   1590   << ResetFlags (); >>
   1591   IDT:Text                            << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>
   1592   Help "=" getStringId ","
   1593   Text "="
   1594   getStringId                         // writes string identifier
   1595   { "," Text "=" getStringId
   1596     "," Flags "=" flagsField ( "\|" flagsField )*  << WriteFlags (); >>
   1597     ","
   1598     Key "=" KNUM:Number               << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>
   1599   }
   1600   ";"
   1601   ;
   1602 
   1603 //*****************************************************************************
   1604 //
   1605 // PARSE:
   1606 //
   1607 //   inventory help = ID, text = ID;
   1608 //   inventory help = ID, text = id, text = ID;
   1609 //
   1610 vfrStatementInventory :
   1611   IDI:Inventory                        << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>
   1612   Help        "=" getStringId ","
   1613   Text        "=" getStringId                 // writes string identifier
   1614   { "," Text  "=" getStringId
   1615   }
   1616   ";"
   1617   ;
   1618 
   1619 //*****************************************************************************
   1620 //
   1621 // PARSE:
   1622 //
   1623 //    restore defaults,
   1624 //      formid  = 4,
   1625 //      prompt  = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
   1626 //      help    = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
   1627 //      flags   = 0,
   1628 //      key     = 0;
   1629 //
   1630 //    save defaults,
   1631 //      formid  = 4,
   1632 //      prompt  = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
   1633 //      help    = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
   1634 //      flags   = 0,
   1635 //      key     = 0;
   1636 //
   1637 vfrStatementSaveRestoreDefaults :
   1638   << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
   1639   ( IDS:Save                            << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>
   1640   | IDR:Restore                         << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>
   1641   )
   1642   Defaults ","
   1643   FormId    "=" FRMID:Number  ","       << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2));
   1644                                            AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());
   1645                                         >>
   1646   Prompt    "=" getStringId ","
   1647   KH:Help   "=" getStringId             << LineNum = KH->getLine(); >>
   1648   {
   1649     "," FF:Flags "=" flagsField ( "\|" flagsField )*  << LineNum = FF->getLine(); >>
   1650   }
   1651   {
   1652     "," Key "=" KNUM:Number             << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
   1653   }
   1654                                         << WriteFlagsKey (KeyValue, LineNum); >>
   1655   ";"
   1656   ;
   1657 
   1658 //*****************************************************************************
   1659 //
   1660 // PARSE:
   1661 //
   1662 //   flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
   1663 //
   1664 //
   1665 flagsField :
   1666   VAL:Number                          << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
   1667   | IF:InteractiveFlag                << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine());    >>
   1668   | MF:ManufacturingFlag              << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine());  >>
   1669   | DF:DefaultFlag                    << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine());        >>
   1670   | NV:NVAccessFlag                   << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine());      >>
   1671   | RR:ResetRequiredFlag              << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
   1672   | LC:LateCheckFlag                  << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine());     >>
   1673   ;
   1674 
   1675 dateTimeSubStatement :
   1676   Prompt  "=" getStringId ","
   1677   Help    "=" getStringId ","
   1678                                       << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
   1679   minMaxStepDefault                   << WriteMinMaxStepDefault (); >>
   1680   ;
   1681 
   1682 vfrStatementCheckBox :
   1683   << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
   1684   IDCB:CheckBox                       << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>
   1685   VarId     "=" vfrStructFieldName[1] ","
   1686   Prompt    "=" getStringId ","
   1687   Help      "=" getStringId ","
   1688   FF:Flags  "=" flagsField ( "\|" flagsField )*  "," << LineNum = FF->getLine(); >>
   1689   {
   1690     Key "=" KV:Number  ","           << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>
   1691   }
   1692                                      << WriteFlagsKey (KeyValue, LineNum); >>
   1693   EndCheckBox ";"
   1694   ;
   1695 
   1696 vfrStatementSubTitle :
   1697   IDS:Subtitle Text "="               << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>
   1698   getStringId                         // writes string indentifier
   1699   ";"
   1700   ;
   1701 
   1702 //*****************************************************************************
   1703 //
   1704 // PARSE:
   1705 //    banner
   1706 //      title = STRING_TOKEN(STR_BANNER_TITLE),
   1707 //      line  1,
   1708 //      align center;     // or left or right
   1709 //
   1710 //    banner,
   1711 //      title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;
   1712 //
   1713 vfrStatementBanner :
   1714   IDB:Banner { "," }                    << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>
   1715   Title "=" getStringId ","
   1716   (
   1717     Line VAL:Number ","                 << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>
   1718     Align
   1719     ( Left                              << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>
   1720     | Center                            << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>
   1721     | Right                             << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>
   1722     ) ";"
   1723   |
   1724     Timeout "=" TO:Number ";"           << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>
   1725                                         << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>
   1726   )
   1727   ;
   1728 
   1729 //*****************************************************************************
   1730 //
   1731 // PARSE:
   1732 //   oneof  varid       = MyNv.OneOfData,
   1733 //          prompt      = STRING_TOKEN(STR_ONE_OF_PROMPT),
   1734 //          help        = STRING_TOKEN(STR_ONE_OF_HELP),
   1735 //          option text = STRING_TOKEN(STR_ONE_OF_TEXT),
   1736 //          value       = 0,
   1737 //          flags       = DEFAULT | INTERACTIVE;
   1738 //
   1739 // supressif/grayoutif are supported inside oneof stmt.
   1740 // We do not restrict the number of oneOfOptionText to >=2, but >=1.
   1741 // The situation that all oneOfOptionText are suppressed is also possiable.
   1742 //
   1743 vfrStatementOneOf :
   1744   << ResetFlags (); >>
   1745   IDOO:OneOf                              << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>
   1746   VarId   "=" vfrStructFieldName[2] ","
   1747   Prompt  "=" getStringId  ","           // writes string identifier
   1748   Help    "=" getStringId  ","           // writes string identifier
   1749   ( oneOfOptionText )+                   // there must be at least 1 option to be choosed, not 2.
   1750   IDEOO:EndOneOf   ";"                    << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>
   1751   ;
   1752 
   1753 //*****************************************************************************
   1754 //
   1755 // PARSE:
   1756 //
   1757 //   orderedlist  varid       = MyNv.OrderedListData,
   1758 //                prompt      = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),
   1759 //                help        = STRING_TOKEN(STR_ORDERED_LIST_HELP),
   1760 //                option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;
   1761 //                -- additional option text --
   1762 //   endlist;
   1763 //
   1764 vfrStatementOrderedList :
   1765   << ResetFlags (); InitOrderedList(); >>
   1766   IDOL:OrderedList                       << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>
   1767   VarId   "=" vfrStructFieldNameArray[1] ","
   1768   Prompt  "=" getStringId  ","           // writes string identifier
   1769   Help    "=" getStringId  ","           // writes string identifier
   1770   orderedListOptionText ( orderedListOptionText )+
   1771   IDEOL:EndList   ";"                    << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>
   1772   ;
   1773 
   1774 //*****************************************************************************
   1775 //
   1776 // PARSE:
   1777 //
   1778 //   option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
   1779 //
   1780 // Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to
   1781 // be set, and value cannot be 0.
   1782 //
   1783 orderedListOptionText :
   1784   << UINT32 KeyValue = 0; >>
   1785   IDO:Option                          << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
   1786   Text      "=" getStringId ","       // writes string identifier
   1787   Value     "=" WVAL:Number ","       <<
   1788                                           if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {
   1789                                             PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL);
   1790                                           } else {
   1791                                             WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2));
   1792                                           }
   1793                                       >>
   1794   FF:Flags  "=" orderedListFlagsField
   1795                 ("\|" orderedListFlagsField )*
   1796   {
   1797     "," Key "=" KV:Number             << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
   1798   }
   1799                                       << WriteFlagsKey (KeyValue, FF->getLine()); >>
   1800   ";"                                 << mOptionCount++; >>
   1801   ;
   1802 
   1803 //*****************************************************************************
   1804 //
   1805 // PARSE:
   1806 //
   1807 //   flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
   1808 //
   1809 // The ordered list flags field cannot have a default.
   1810 //
   1811 orderedListFlagsField :
   1812   VAL:Number                          << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
   1813   | IF:InteractiveFlag                << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine());    >>
   1814   | MF:ManufacturingFlag              << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine());  >>
   1815   | NV:NVAccessFlag                   << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine());      >>
   1816   | RR:ResetRequiredFlag              << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
   1817   | LC:LateCheckFlag                  << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine());     >>
   1818   | DF:DefaultFlag                    << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>
   1819   ;
   1820 
   1821 //
   1822 // Parse references to VFR structure field names of form "MyNvStructure.Field".
   1823 // This implementation is specific to strings, passwords, and references in an
   1824 // ordered list statement because we want to specify the size of the entire
   1825 // field, rather than just one element. Then call a function to write out its
   1826 // offset and length.
   1827 //
   1828 vfrStructFieldNameArray[int FieldWidth] :
   1829   << int ArrayIndex = 1; char IsArrayIndex = 0; >>
   1830   SName:StringIdentifier
   1831   "."
   1832   SFieldName:StringIdentifier
   1833   { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
   1834             <<
   1835                 WriteFieldOffset (1,
   1836                                   SName->getText(),
   1837                                   SName->getLine(),
   1838                                   SFieldName->getText(),
   1839                                   SFieldName->getLine(),
   1840                                   ArrayIndex,
   1841                                   IsArrayIndex,
   1842                                   FieldWidth,
   1843                                   1
   1844                                   );
   1845             >>
   1846   ;
   1847 
   1848 //
   1849 // Parse references to VFR structure field names of form "MyNvStructure.Field",
   1850 // then call a function to write out its offset and length.
   1851 //
   1852 vfrStructFieldName[int FieldWidth] :
   1853   << int ArrayIndex = 1; char IsArrayIndex = 0; >>
   1854   SName:StringIdentifier
   1855   "."
   1856   SFieldName:StringIdentifier
   1857   { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
   1858             <<
   1859                 WriteFieldOffset (1,
   1860                                   SName->getText(),
   1861                                   SName->getLine(),
   1862                                   SFieldName->getText(),
   1863                                   SFieldName->getLine(),
   1864                                   ArrayIndex,
   1865                                   IsArrayIndex,
   1866                                   FieldWidth,
   1867                                   0
   1868                                   );
   1869             >>
   1870   ;
   1871 
   1872 //*****************************************************************************
   1873 //
   1874 // PARSE:
   1875 //
   1876 //   MyNvStructure.FieldName[4]
   1877 //
   1878 // Parse references to VFR structure field names of form "MyNvStructure.Field",
   1879 // then call a function to write out the offset with no length.
   1880 //
   1881 vfrStructFieldNameNL[int FieldWidth] :
   1882   << int ArrayIndex = 1; char IsArrayIndex = 0; >>
   1883   SName:StringIdentifier
   1884   "."
   1885   SFieldName:StringIdentifier
   1886   { OpenBracket AIndex:Number CloseBracket   << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
   1887             <<
   1888                 WriteFieldOffset (0,
   1889                                   SName->getText(),
   1890                                   SName->getLine(),
   1891                                   SFieldName->getText(),
   1892                                   SFieldName->getLine(),
   1893                                   ArrayIndex,
   1894                                   IsArrayIndex,
   1895                                   FieldWidth,
   1896                                   0
   1897                                   );
   1898             >>
   1899   ;
   1900 
   1901 //*****************************************************************************
   1902 //
   1903 // PARSE:
   1904 //   suppressif TRUE OR FALSE;
   1905 //   grayoutif FALSE OR TRUE;
   1906 //     option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
   1907 //     option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;
   1908 //   endif;
   1909 //
   1910 oneOfOptionText :
   1911   suppressIfOptionText    |
   1912   grayOutIfOptionText     |
   1913   commonOptionText
   1914   ;
   1915 
   1916 suppressIfOptionText :
   1917   << ResetFlags (); >>
   1918   OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
   1919   {
   1920     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1921   }
   1922   << WriteFlags (); >> //  write the flags field
   1923   vfrBooleanExpression
   1924   ";"
   1925   { suppressIfGrayOutIf } ( commonOptionText )+
   1926   ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
   1927   ;
   1928 
   1929 grayOutIfOptionText :
   1930   << ResetFlags (); >>
   1931   OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
   1932   {
   1933     FF:Flags  "=" flagsField ( "\|" flagsField )* ","
   1934   }
   1935   << WriteFlags (); >> //  write the flags field
   1936   vfrBooleanExpression
   1937   ";"
   1938   { grayoutIfSuppressIf } ( commonOptionText )+
   1939   ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
   1940   ;
   1941 
   1942 commonOptionText :
   1943   << UINT32 KeyValue = 0; >>
   1944   IDO:Option                      << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
   1945   Text      "=" getStringId ","   // writes string identifier
   1946   Value     "=" WVal:Number ","   << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>
   1947   FF:Flags  "=" flagsField  ("\|" flagsField )*
   1948   {
   1949     "," Key "=" KV:Number         << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
   1950   }
   1951                                   << WriteFlagsKey (KeyValue, FF->getLine()); >>
   1952   ";"                             << mOptionCount++; >>
   1953   ;
   1954 
   1955 //
   1956 // Gets a string identifier. It must be a numeric value of form:
   1957 //
   1958 //   STRING_TOKEN(100)
   1959 //
   1960 getStringId :
   1961   << unsigned short StrId; >>
   1962   StringToken OpenParen
   1963   IdVal:Number             << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >>
   1964   CloseParen
   1965   ;
   1966 
   1967 //******************************************************************************
   1968 //
   1969 // Parser class definition.
   1970 //
   1971 class EfiVfrParser {
   1972 <<
   1973 //
   1974 // Parser definitions go here
   1975 //
   1976 private:
   1977   STRUCT_DEFINITION   *mFirstStructDefinition;
   1978   STRUCT_DEFINITION   *mLastStructDefinition;
   1979   INT32               mNvDataStructSize;
   1980   INT32               mNonNvDataStructSize;
   1981   //
   1982   // Flag to indicate that we're processing a ideqid VFR statement so that
   1983   // we can do late checks on the statement.
   1984   //
   1985   INT32               mIdEqIdStmt;
   1986   INT32               mLastNVVariableDataSize;
   1987   GOTO_REFERENCE      *mGotoReferences;
   1988   FORM_ID_VALUE       *mFormIdValues;
   1989   VfrOpcodeHandler    mOpcodeHandler;
   1990   UINT16_LIST         *mUint16List;
   1991   UINT16_LIST         *mLastUint16;
   1992   UINT16_LIST         *mDefinedLabels;
   1993   UINT16_LIST         *mDefinedVarStoreId;
   1994   UINT16_LIST         *mLastDefinedVarStoreId;
   1995   UINT32              mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;
   1996   UINT32              mStmtFlags;
   1997   UINT32              mSubStmtFlags;
   1998   UINT32              mSubStmtFlagsLineNum;
   1999   EFI_GUID            mFormSetGuid;
   2000   UINT8               mNvDataStructDefined;
   2001   UINT16              mClass, mSubclass;
   2002   UINT32              mIfStart;
   2003   UINT32              mOptionCount;  // how many "option" fields in a given statement
   2004   UINT32              mLastVarIdSize;
   2005   UINT8               mOutput;
   2006 public:
   2007 
   2008 VOID
   2009 EfiVfrParser::SetIfStart (
   2010   UINT32 LineNum
   2011   )
   2012 /*++
   2013 
   2014 Routine Description:
   2015   Invoked during VFR parsing when an "if" is encountered. Save the
   2016   source line number so we can point to it if we don't find a
   2017   corresponding endif later.
   2018 
   2019 Arguments:
   2020   LineNum - source line number where the "if" was parsed.
   2021 
   2022 Returns:
   2023   None
   2024 
   2025 --*/
   2026 {
   2027   mIfStart = LineNum;
   2028 }
   2029 VOID
   2030 EfiVfrParser::SetClass (
   2031   UINT32 LineNum,
   2032   UINT32 Value
   2033   )
   2034 /*++
   2035 
   2036 Routine Description:
   2037   Invoked during VFR parsing when a "class" statement is found. Check the
   2038   range on the class value and save it for later.
   2039 
   2040 Arguments:
   2041   LineNum - source line number where the class statement was parsed.
   2042   Value   - the class value
   2043 
   2044 Returns:
   2045   None
   2046 
   2047 --*/
   2048 {
   2049   if (Value & 0xFFFF0000) {
   2050     PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
   2051   }
   2052   mClass |= (UINT16)Value;
   2053 }
   2054 VOID
   2055 EfiVfrParser::SetSubclass (
   2056   UINT32 LineNum,
   2057   UINT32 Value
   2058   )
   2059 /*++
   2060 
   2061 Routine Description:
   2062   Invoked during VFR parsing when a subclass statement is found. Check the
   2063   range on the value and save it for later.
   2064 
   2065 Arguments:
   2066   LineNum - source line number where the class statement was parsed.
   2067   Value   - the subclass value from the VFR statement
   2068 
   2069 Returns:
   2070   None
   2071 
   2072 --*/
   2073 {
   2074   if (Value & 0xFFFF0000) {
   2075     PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
   2076   }
   2077   mSubclass |= (UINT16)Value;
   2078 }
   2079 VOID EfiVfrParser::WriteClass ()
   2080 {
   2081   WriteWord (mClass);
   2082   mClass = 0;
   2083 }
   2084 VOID EfiVfrParser::WriteSubclass ()
   2085 {
   2086   WriteWord (mSubclass);
   2087   mSubclass = 0;
   2088 }
   2089 VOID EfiVfrParser::WriteIfrBytes ()
   2090 {
   2091   mOpcodeHandler.WriteIfrBytes ();
   2092 }
   2093 VOID
   2094 EfiVfrParser::WriteFlagsKey (
   2095   UINT32 KeyValue,
   2096   UINT32 LineNum
   2097   )
   2098 /*++
   2099 
   2100 Routine Description:
   2101   Write out the flags and key values from the previous VFR statement.
   2102   Many statements take a flags/key pair. If not specified, then 0
   2103   values are written out. However do not allow an interactive flags field
   2104   to be specified if no key value is specified. Also, if NV_ACCESS flag
   2105   is set but INTERACTIVE is not, then set interactive and issue a warning.
   2106 
   2107 Arguments:
   2108   KeyValue  - the key value from the VFR statement
   2109   LineNum   - source line number where the statement was parsed
   2110 
   2111 Returns:
   2112   None
   2113 
   2114 --*/
   2115 {
   2116   if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {
   2117     PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");
   2118   }
   2119   if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {
   2120     PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");
   2121     mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;
   2122   }
   2123   WriteFlags ();
   2124   WriteWord (KeyValue);
   2125 }
   2126 VOID
   2127 EfiVfrParser::InitOrderedList ()
   2128 {
   2129   mOptionCount = 0;
   2130 }
   2131 VOID
   2132 EfiVfrParser::EndOrderedList (
   2133   UINT32 LineNum
   2134   )
   2135 {
   2136   if (mLastVarIdSize < mOptionCount) {
   2137     PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
   2138   }
   2139 }
   2140 VOID
   2141 EfiVfrParser::ResetFlags ()
   2142 /*++
   2143 
   2144 Routine Description:
   2145 
   2146   Flags are set for each substatement in a given one-of statement.
   2147   To make sure there are no conflicts, for example setting DEFAULT on
   2148   more than one substatement, we keep track of the flags at a statement
   2149   level and a substatement level. This function resets the flags so
   2150   we get a fresh start.
   2151 
   2152 Arguments:
   2153   None
   2154 
   2155 Returns:
   2156   None
   2157 
   2158 --*/
   2159 {
   2160   mStmtFlags = 0;
   2161   mSubStmtFlagsLineNum = 0;
   2162   mSubStmtFlags = 0;
   2163 }
   2164 //
   2165 // Test validity of flags value for a one-of statement.
   2166 //
   2167 VOID
   2168 EfiVfrParser::TestOneOfFlags (
   2169   UINT32 LineNum
   2170   )
   2171 {
   2172   //
   2173   // One of the fields must have had the default bit set
   2174   //
   2175   if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {
   2176     PrintWarningMessage (LineNum, "default value must be specified", NULL);
   2177   }
   2178 }
   2179 VOID
   2180 EfiVfrParser::SetFlags (
   2181   UINT32 Flags,
   2182   UINT32 LineNum
   2183   )
   2184 {
   2185   //
   2186   // Check for redefinitions and invalid combinations
   2187   //
   2188   if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {
   2189     PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");
   2190   }
   2191   if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {
   2192     PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");
   2193   }
   2194   mSubStmtFlags |= Flags;
   2195   mSubStmtFlagsLineNum = LineNum;
   2196 }
   2197 VOID
   2198 EfiVfrParser::WriteFlags ()
   2199 {
   2200   //
   2201   // Check value for validity
   2202   //
   2203   if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT |
   2204                         EFI_IFR_FLAG_MANUFACTURING |
   2205                         EFI_IFR_FLAG_INTERACTIVE |
   2206                         EFI_IFR_FLAG_NV_ACCESS |
   2207                         EFI_IFR_FLAG_RESET_REQUIRED |
   2208                         EFI_IFR_FLAG_LATE_CHECK )) {
   2209     PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);
   2210   }
   2211   WriteByte ((UINT8)mSubStmtFlags, 'F');
   2212   //
   2213   // We can now clear the substatement flags
   2214   //
   2215   mStmtFlags |= mSubStmtFlags;
   2216   mSubStmtFlags = 0;
   2217 }
   2218 //
   2219 // When we parse a min/max/step/default sequence, save off the values for
   2220 // later use. Call this first to init the values.
   2221 //
   2222 VOID
   2223 EfiVfrParser::InitMinMaxStepDefault ()
   2224 {
   2225   mMinimumValue         = 0;
   2226   mMaximumValue         = 0;
   2227   mStepValue            = 1;
   2228   mDefaultValue         = 0;
   2229 }
   2230 VOID
   2231 EfiVfrParser::WriteMinMaxStepDefault ()
   2232 {
   2233   WriteWord (mMinimumValue);
   2234   WriteWord (mMaximumValue);
   2235   WriteWord (mStepValue);
   2236   WriteWord (mDefaultValue);
   2237 }
   2238 VOID
   2239 EfiVfrParser::SetMinMaxStepDefault (
   2240   UINT16  Value,
   2241   INT32   MMSD,
   2242   INT32   LineNum
   2243   )
   2244 {
   2245   UINT16 TempValue;
   2246   //
   2247   // Min specified
   2248   //
   2249   if (MMSD == 0) {
   2250     mMinimumValue = Value;
   2251     mDefaultValue = Value;
   2252   //
   2253   // Max specified
   2254   //
   2255   } else if (MMSD == 1) {
   2256     mMaximumValue = Value;
   2257     //
   2258     // If min > max, then swap the values. That includes resetting the default
   2259     // value as well.
   2260     //
   2261     if (mMinimumValue > mMaximumValue) {
   2262       PrintWarningMessage (LineNum, NULL, "maximum < minimum");
   2263       TempValue = Value;
   2264       mMaximumValue = mMinimumValue;
   2265       mMinimumValue = TempValue;
   2266       mDefaultValue = mMinimumValue;
   2267     }
   2268   //
   2269   // Step specified
   2270   //
   2271   } else if (MMSD == 2) {
   2272     mStepValue = Value;
   2273   //
   2274   // Default specified. Make sure min <= default <= max.
   2275   //
   2276   } else if (MMSD == 3) {
   2277     mDefaultValue = Value;
   2278     if (mMinimumValue > Value) {
   2279       PrintErrorMessage (LineNum, NULL, "default value < minimum value");
   2280     } else if (Value > mMaximumValue) {
   2281       PrintErrorMessage (LineNum, NULL, "default value > maximum value");
   2282     }
   2283   } else {
   2284     PrintErrorMessage (LineNum, "application error", "internal MMSD error");
   2285   }
   2286 }
   2287 VOID
   2288 EfiVfrParser::AddLabel (
   2289   UINT32 LabelNumber,
   2290   UINT32 LineNum
   2291   )
   2292 {
   2293   UINT16_LIST *Label;
   2294 
   2295   //
   2296   // Added a label from the user VFR script. Make sure they haven't already
   2297   // defined the same label elsewhere
   2298   //
   2299   for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {
   2300     if (Label->Value == LabelNumber) {
   2301       PrintErrorMessage (LineNum, NULL, "label already defined");
   2302       PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");
   2303       break;
   2304     }
   2305   }
   2306   Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
   2307   if (Label == NULL) {
   2308     PrintErrorMessage (0, NULL, "memory allocation error");
   2309     return;
   2310   }
   2311   memset ((char *)Label, 0, sizeof (UINT16_LIST));
   2312   Label->Value = LabelNumber;
   2313   Label->LineNum = LineNum;
   2314   Label->Next = mDefinedLabels;
   2315   mDefinedLabels = Label;
   2316 }
   2317 VOID
   2318 EfiVfrParser::QueueIdEqValList (
   2319   UINT16 Value
   2320   )
   2321 {
   2322   UINT16_LIST   *U16;
   2323 
   2324   U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
   2325   if (U16 == NULL) {
   2326     Error (UTILITY_NAME, 0, 0, NULL, "memory allocation failed");
   2327   } else {
   2328     memset ((char *)U16, 0, sizeof (UINT16_LIST));
   2329     U16->Value = Value;
   2330     if (mUint16List == NULL) {
   2331       mUint16List = U16;
   2332     } else {
   2333       mLastUint16->Next = U16;
   2334     }
   2335     mLastUint16 = U16;
   2336   }
   2337 }
   2338 VOID
   2339 EfiVfrParser::FlushQueueIdEqValList ()
   2340 {
   2341   UINT32 Count;
   2342 
   2343   //
   2344   // We queued up a list of IdEqValList items. The IFR requires a count
   2345   // followed by the actual values. Do it.
   2346   //
   2347   Count = 0;
   2348   mLastUint16 = mUint16List;
   2349   while (mLastUint16 != NULL) {
   2350     Count++;
   2351     mLastUint16 = mLastUint16->Next;
   2352   }
   2353   // BUGBUG -- check for more than 16K items?
   2354   WriteWord (Count);
   2355   //
   2356   // Now write the values.
   2357   //
   2358   mLastUint16 = mUint16List;
   2359   while (mLastUint16 != NULL) {
   2360     WriteWord ((UINT32)mLastUint16->Value);
   2361     mLastUint16 = mLastUint16->Next;
   2362   }
   2363   //
   2364   // Free up the list
   2365   //
   2366   mLastUint16 = mUint16List;
   2367   while (mUint16List != NULL) {
   2368     mLastUint16 = mUint16List->Next;
   2369     free (mUint16List);
   2370     mUint16List = mLastUint16;
   2371   }
   2372 }
   2373 VOID
   2374 EfiVfrParser::PrintErrorMessage (
   2375   UINT32              LineNum,
   2376   INT8                *Msg1,
   2377   INT8                *Msg2
   2378   )
   2379 {
   2380   char *FileName;
   2381 
   2382   if (LineNum != 0) {
   2383     FileName = ConvertLineNumber ((UINT32 *)&LineNum);
   2384     Error (FileName, LineNum, 0, Msg1, Msg2);
   2385   } else {
   2386     Error (UTILITY_NAME, 0, 0, Msg1, Msg2);
   2387   }
   2388 }
   2389 VOID
   2390 EfiVfrParser::PrintWarningMessage (
   2391   UINT32              LineNum,
   2392   INT8                *Msg1,
   2393   INT8                *Msg2
   2394   )
   2395 {
   2396   char *FileName;
   2397 
   2398   if (LineNum != 0) {
   2399     FileName = ConvertLineNumber ((UINT32 *)&LineNum);
   2400     Warning (FileName, LineNum, 0, Msg1, Msg2);
   2401   } else {
   2402     Warning (UTILITY_NAME, 0, 0, Msg1, Msg2);
   2403   }
   2404 }
   2405 VOID
   2406 EfiVfrParser::syn (
   2407   ANTLRAbstractToken  *Tok,
   2408   ANTLRChar           *Egroup,
   2409   SetWordType         *Eset,
   2410   ANTLRTokenType      ETok,
   2411   INT32               Huh
   2412   )
   2413 /*++
   2414 
   2415 Routine Description:
   2416   Called by the parser base class as a result of parse syntax errors.
   2417 
   2418 Arguments:
   2419   Tok     - token that caused the error
   2420   Egroup  - not sure
   2421   Eset    - index in token table of the expected token
   2422   Huh     - not sure
   2423 
   2424 Returns:
   2425   NA
   2426 
   2427 --*/
   2428 {
   2429   char    *FileName;
   2430   UINT32  LineNum;
   2431 
   2432   LineNum = Tok->getLine ();
   2433   FileName = ConvertLineNumber ((UINT32 *)&LineNum);
   2434   //
   2435   // Sometimes the token number is 0, in which case I don't know what to
   2436   // print.
   2437   //
   2438   if (ETok == 0) {
   2439     Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");
   2440   } else {
   2441     //
   2442     // If we were expecting an endif, then report the line where the corresponding
   2443     // IF began.
   2444     //
   2445     if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {
   2446       LineNum = mIfStart;
   2447       FileName = ConvertLineNumber (&LineNum);
   2448       Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);
   2449     } else {
   2450       Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);
   2451     }
   2452   }
   2453 }
   2454 
   2455 VOID
   2456 EfiVfrParser::init()
   2457 /*++
   2458 
   2459 Routine Description:
   2460   Initializations function for our parser.
   2461 
   2462 Arguments:
   2463   None.
   2464 
   2465 Returns:
   2466   None.
   2467 
   2468 --*/
   2469 {
   2470   ANTLRParser::init();
   2471 
   2472   //
   2473   // Used for queuing a variable list of UINT16's
   2474   //
   2475   mUint16List               = NULL;
   2476   mLastUint16               = NULL;
   2477   mFirstStructDefinition    = NULL;
   2478   mLastStructDefinition     = NULL;
   2479   mNvDataStructSize         = 0;
   2480   mNonNvDataStructSize      = 0;
   2481   mNvDataStructDefined      = 0;
   2482   mGotoReferences           = NULL;
   2483   mFormIdValues             = NULL;
   2484   mDefinedLabels            = NULL;
   2485   mClass                    = 0;
   2486   mSubclass                 = 0;
   2487   mIfStart                  = 0;
   2488   mDefinedVarStoreId        = NULL;
   2489   mLastDefinedVarStoreId    = NULL;
   2490   mIdEqIdStmt               = 0;
   2491   mLastNVVariableDataSize   = 0;
   2492 
   2493   memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));
   2494 }
   2495 //
   2496 // Destructor for the parser.
   2497 //
   2498 EfiVfrParser::~EfiVfrParser(VOID)
   2499 {
   2500   Cleanup();
   2501 }
   2502 VOID
   2503 EfiVfrParser::Cleanup (VOID)
   2504 /*++
   2505 
   2506 Routine Description:
   2507   Free memory allocated during parsing
   2508 
   2509 Arguments:
   2510   None.
   2511 
   2512 Returns:
   2513   None.
   2514 
   2515 --*/
   2516 {
   2517   STRUCT_DEFINITION         *NextStruct;
   2518   STRUCT_FIELD_DEFINITION   *NextField;
   2519   UINT8                     Buff[6];
   2520   UINT16_LIST               *NextU16List;
   2521 
   2522   //
   2523   // Free up the structure definitions if any
   2524   //
   2525   while (mFirstStructDefinition != NULL) {
   2526     //
   2527     // Free up all the fields for this struct
   2528     //
   2529     while (mFirstStructDefinition->Field != NULL) {
   2530       NextField = mFirstStructDefinition->Field->Next;
   2531       free (mFirstStructDefinition->Field->Name);
   2532       free (mFirstStructDefinition->Field);
   2533       mFirstStructDefinition->Field = NextField;
   2534     }
   2535     NextStruct = mFirstStructDefinition->Next;
   2536     free (mFirstStructDefinition->Name);
   2537     free (mFirstStructDefinition);
   2538     mFirstStructDefinition = NextStruct;
   2539   }
   2540   //
   2541   // Free up the goto references and form id defines
   2542   //
   2543   FreeGotoReferences ();
   2544   //
   2545   // Free up label list
   2546   //
   2547   while (mDefinedLabels != NULL) {
   2548     NextU16List = mDefinedLabels->Next;
   2549     delete (mDefinedLabels);
   2550     mDefinedLabels = NextU16List;
   2551   }
   2552   //
   2553   // Free up the list of defined variable storage IDs
   2554   //
   2555   while (mDefinedVarStoreId != NULL) {
   2556     NextU16List = mDefinedVarStoreId->Next;
   2557     delete (mDefinedVarStoreId);
   2558     mDefinedVarStoreId = NextU16List;
   2559   }
   2560 }
   2561 
   2562 INT32
   2563 EfiVfrParser::AtoX (
   2564   INT8    *HexString,
   2565   INT32   NumBytes,
   2566   UINT32  *HexValue
   2567   )
   2568 /*++
   2569 
   2570 Routine Description:
   2571   Given a pointer to a ascii hex string, convert to a number with the given
   2572   number of bytes.
   2573 
   2574 Arguments:
   2575   HexString   - pointer to a string of format 30BCA
   2576   Size        - number of bytes to convert
   2577   HexValue    - return result
   2578 
   2579 Returns:
   2580   The number of bytes converted.
   2581 
   2582 --*/
   2583 {
   2584   INT32 Count;
   2585   INT32 Value;
   2586 
   2587   *HexValue = 0;
   2588   Count = 0;
   2589   while (Count < NumBytes) {
   2590     if ((*HexString >= '0') && (*HexString <= '9')) {
   2591       Value = *HexString - '0';
   2592     } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
   2593       Value = *HexString - 'a' + 10;
   2594     } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
   2595       Value = *HexString - 'A' + 10;
   2596     } else {
   2597       return Count;
   2598     }
   2599     HexString++;
   2600     *HexValue = (*HexValue << 4) | Value;
   2601     if ((*HexString >= '0') && (*HexString <= '9')) {
   2602       Value = *HexString - '0';
   2603     } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
   2604       Value = *HexString - 'a' + 10;
   2605     } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
   2606       Value = *HexString - 'A' + 10;
   2607     } else {
   2608       return Count;
   2609     }
   2610     *HexValue = (*HexValue << 4) | Value;
   2611     HexString++;
   2612     Count++;
   2613   }
   2614   return Count;
   2615 }
   2616 VOID
   2617 EfiVfrParser::WriteGuidValue (
   2618   UINT32       TokenLineNum,
   2619   INT8         *G1,
   2620   INT8         *G2,
   2621   INT8         *G3,
   2622   INT8         *G4,
   2623   INT8         *G5,
   2624   INT8         *G6,
   2625   INT8         *G7,
   2626   INT8         *G8,
   2627   INT8         *G9,
   2628   INT8         *G10,
   2629   INT8         *G11
   2630   )
   2631 /*++
   2632 
   2633 Routine Description:
   2634   A Guid was parsed, likely of format:
   2635   #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }
   2636 
   2637   Write out the value.
   2638 
   2639 Arguments:
   2640   TokenLineNum   - line number where the guid was used
   2641   G1-G11         - the 11 fields of the guid value
   2642 
   2643 Returns:
   2644   None.
   2645 
   2646 --*/
   2647 {
   2648   UINT32        Value;
   2649   INT32         Loop;
   2650   INT8          *Cptr;
   2651 
   2652   mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);
   2653   mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);
   2654   mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);
   2655   mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);
   2656   mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);
   2657   mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);
   2658   mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);
   2659   mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);
   2660   mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);
   2661   mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);
   2662   mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);
   2663 
   2664   WriteDWord (mFormSetGuid.Data1, 'G');
   2665   WriteWord (mFormSetGuid.Data2);
   2666   WriteWord (mFormSetGuid.Data3);
   2667   WriteByte (mFormSetGuid.Data4[0], 0);
   2668   WriteByte (mFormSetGuid.Data4[1], 0);
   2669   WriteByte (mFormSetGuid.Data4[2], 0);
   2670   WriteByte (mFormSetGuid.Data4[3], 0);
   2671   WriteByte (mFormSetGuid.Data4[4], 0);
   2672   WriteByte (mFormSetGuid.Data4[5], 0);
   2673   WriteByte (mFormSetGuid.Data4[6], 0);
   2674   WriteByte (mFormSetGuid.Data4[7], 0);
   2675 }
   2676 VOID
   2677 EfiVfrParser::WriteFieldOffset (
   2678   INT8    WriteLength,
   2679   INT8    *StructName,
   2680   INT32   LineNum1,
   2681   INT8    *FieldName,
   2682   INT32   LineNum2,
   2683   INT32   ArrayIndex,
   2684   INT8    IsArrayIndex,
   2685   INT32   FieldWidth,
   2686   INT8    WriteArraySize
   2687   )
   2688 /*++
   2689 
   2690 Routine Description:
   2691   A VFR script referenced the NV store structure. Given the structure's name
   2692   and the field's name, write the offset of the field to the output file.
   2693 
   2694 Arguments:
   2695   WriteLength     - write the field length byte out
   2696   StructName      - name of the NV store structure
   2697   LineNum1        - line number in the VFR where we are (for error printing)
   2698   FieldName       - the name of the field within the NV store structure
   2699   LineNum2        - line number in the VFR where FieldName is referenced
   2700   ArrayIndex      - the index specified, for example NV_DATA.Field[ArrayIndex]
   2701   IsArrayIndex    - non-zero if an array index was specified
   2702   FieldWidth      - expected size for the Field (1 byte? 2 bytes?)
   2703   WriteArraySize  - write the size of the entire field, not the size of a single element
   2704 
   2705 Returns:
   2706   None.
   2707 
   2708 --*/
   2709 {
   2710   STRUCT_DEFINITION         *StructDef;
   2711   STRUCT_FIELD_DEFINITION   *FieldDef;
   2712   UINT32                    Offset;
   2713   UINT32                    VarSize;
   2714   INT8                      Msg[100];
   2715   //
   2716   // If we're writing an array size, then they better have referenced the field without an
   2717   // index.
   2718   //
   2719   if (WriteArraySize && IsArrayIndex) {
   2720     sprintf (Msg, "array index specified where an array is required");
   2721     PrintErrorMessage (LineNum2, FieldName, Msg);
   2722     return;
   2723   }
   2724 
   2725   //
   2726   // The reference index starts at 1 not 0
   2727   //
   2728   if (IsArrayIndex && (ArrayIndex < 1)) {
   2729     printf ("WARNING: array index shouldn't be less than 1");
   2730   }
   2731   //
   2732   // Look through our list of known structures for a match
   2733   //
   2734   for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
   2735     //
   2736     // Check for matching structure name
   2737     //
   2738     if (strcmp (StructDef->Name, StructName) == 0) {
   2739       //
   2740       // Mark it as referenced (for debug purposes only). Check the
   2741       // flag that indicates that we have already found a varstore VFR
   2742       // statement for it.
   2743       //
   2744       StructDef->Referenced++;
   2745       if (StructDef->VarStoreIdValid == 0) {
   2746         //
   2747         // Set it valid so we don't flag it multiple times, then emit the error
   2748         //
   2749         StructDef->VarStoreIdValid = 1;
   2750         PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");
   2751       }
   2752       //
   2753       // Let the opcode-handler know which variable storage we're now using
   2754       //
   2755       if (mIdEqIdStmt) {
   2756         mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);
   2757       } else {
   2758         mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);
   2759       }
   2760       //
   2761       // Found matching structure name. Now find the matching field name
   2762       //
   2763       for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
   2764         if (strcmp (FieldDef->Name, FieldName) == 0) {
   2765           //
   2766           // Make sure the variable size is valid
   2767           //
   2768           if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {
   2769             sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');
   2770             PrintErrorMessage (LineNum2, FieldName, Msg);
   2771           }
   2772           //
   2773           // If they specified an index (MyVfrData.FieldX[10]), then make sure that the
   2774           // data structure was declared as an array, and that the index is in bounds.
   2775           // If they did not specify an index, then we'll assume 0. This is required for
   2776           // strings.
   2777           //
   2778           if (IsArrayIndex) {
   2779             VarSize = FieldDef->DataSize;
   2780             if (FieldDef->IsArray == 0) {
   2781               PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");
   2782               return;
   2783             }
   2784             if (FieldDef->ArrayLength < ArrayIndex) {
   2785               PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");
   2786               return;
   2787             }
   2788           } else {
   2789             if (FieldDef->IsArray) {
   2790               VarSize = FieldDef->DataSize * FieldDef->ArrayLength;
   2791             } else {
   2792               VarSize = FieldDef->DataSize;
   2793             }
   2794           }
   2795           //
   2796           // If we're in the middle of a ideqid VFR statement, then this is the second
   2797           // variable ID that we're now processing. Make sure that its size is the same
   2798           // as the first variable.
   2799           //
   2800           if (mIdEqIdStmt) {
   2801             if (mLastVarIdSize != VarSize) {
   2802               PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");
   2803               return;
   2804             }
   2805           }
   2806           mLastVarIdSize = VarSize;
   2807           //
   2808           // If we're supposed to write an array size, then require it to be an array
   2809           //
   2810           if (WriteArraySize && !FieldDef->IsArray) {
   2811             PrintErrorMessage (LineNum2, FieldName, "array required");
   2812             return;
   2813           }
   2814           //
   2815           // Write the variable offset and size. If we're in the non-NV structure, then
   2816           // set the offset beyond the NV data structure size.
   2817           //
   2818           Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);
   2819           if (StructDef->IsNonNV) Offset += mNvDataStructSize;
   2820           WriteWord (Offset);
   2821           if (WriteLength) {
   2822             if (WriteArraySize) {
   2823               if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {
   2824                 PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");
   2825                 return;
   2826               }
   2827               WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);
   2828             } else {
   2829               WriteByte (FieldDef->DataSize, 0);
   2830             }
   2831           }
   2832           return;
   2833         }
   2834       }
   2835       sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);
   2836       PrintErrorMessage (LineNum2, Msg, NULL);
   2837       PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);
   2838       return;
   2839     }
   2840   }
   2841   //
   2842   // The structure was not found in the defined list. See if it's the "Date" structure
   2843   //
   2844   if (strcmp (StructName, "Date") == 0) {
   2845     //
   2846     // BUGBUG -- remove support for Date and Time as valid structure
   2847     // names. They should use the NON_NV_DATA_MAP structure for this.
   2848     //
   2849     // Someone specified Date.Years|Months|Days
   2850     // BUGBUG -- define some constants for the IDs used here
   2851     // Length == 0 implies that this is not user NV data storage.
   2852     //
   2853     if (strcmp (FieldName, "Year") == 0) {
   2854       //
   2855       // Write ID (offset), ID, and size
   2856       //
   2857       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);
   2858       if (WriteLength) {
   2859         WriteByte (0, 0);
   2860       }
   2861     } else if (strcmp (FieldName, "Month") == 0) {
   2862       //
   2863       // Write ID (offset), ID, and size
   2864       //
   2865       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);
   2866       if (WriteLength) {
   2867         WriteByte (0, 0);
   2868       }
   2869     } else if (strcmp (FieldName, "Day") == 0) {
   2870       //
   2871       // Write ID (offset), ID, and size
   2872       //
   2873       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);
   2874       if (WriteLength) {
   2875         WriteByte (0, 0);
   2876       }
   2877     } else {
   2878       PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");
   2879     }
   2880     return;
   2881   } else if (strcmp (StructName, "Time") == 0) {
   2882     //
   2883     // Someone specified Time.Hours|Minutes|Seconds
   2884     // BUGBUG -- define some constants for the IDs used here
   2885     //
   2886     if (strcmp (FieldName, "Hours") == 0) {
   2887       //
   2888       // Write ID (offset), ID, and size
   2889       //
   2890       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);
   2891       if (WriteLength) {
   2892         WriteByte (0, 0);
   2893       }
   2894     } else if (strcmp (FieldName, "Minutes") == 0) {
   2895       //
   2896       // Write ID (offset), ID, and size
   2897       //
   2898       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);
   2899       if (WriteLength) {
   2900         WriteByte (0, 0);
   2901       }
   2902     } else if (strcmp (FieldName, "Seconds") == 0) {
   2903       //
   2904       // Write ID (offset), ID, and size
   2905       //
   2906       WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);
   2907       if (WriteLength) {
   2908         WriteByte (0, 0);
   2909       }
   2910     } else {
   2911       PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");
   2912     }
   2913     return;
   2914   } else {
   2915     PrintErrorMessage (LineNum1, StructName, "undefined structure");
   2916     return;
   2917   }
   2918 }
   2919 VOID
   2920 EfiVfrParser::StartStructDefinition (
   2921   INT32  IsNonNV,
   2922   INT32  LineNum
   2923   )
   2924 /*++
   2925 
   2926 Routine Description:
   2927   Called when we encounter a new "struct _MY_STRUCT..." statement while parsing.
   2928   Initialize internal data and structures for parsing the fields of the structure.
   2929 
   2930 Arguments:
   2931   LineNum  - line number in the source file (for error reporting purposes)
   2932   IsNonNv  - flag indicating (if nonzero) that the variable referred to is not in
   2933              the standard NV store.
   2934 Returns:
   2935   None
   2936 
   2937 --*/
   2938 {
   2939   STRUCT_DEFINITION *StructDef;
   2940   //
   2941   // Allocate memory for the structure record
   2942   //
   2943   StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));
   2944   memset (StructDef, 0, sizeof (STRUCT_DEFINITION));
   2945   StructDef->LineNum = LineNum;
   2946   //
   2947   // Set flag indicating non-NV data structure or not
   2948   //
   2949   StructDef->IsNonNV = IsNonNV;
   2950   //
   2951   // Add it to the end of our linked list. If it's the first one
   2952   // defined, then it's the default varstore ID, so set it valid.
   2953   //
   2954   if (mFirstStructDefinition == NULL) {
   2955     mFirstStructDefinition = StructDef;
   2956     StructDef->VarStoreIdValid = 1;
   2957   } else {
   2958     mLastStructDefinition->Next = StructDef;
   2959   }
   2960   mLastStructDefinition = StructDef;
   2961 }
   2962 VOID
   2963 EfiVfrParser::EndStructDefinition (
   2964   INT8   *StructName,
   2965   INT32  LineNum
   2966   )
   2967 {
   2968   STRUCT_DEFINITION         *StructDef;
   2969   STRUCT_FIELD_DEFINITION   *FieldDef;
   2970   UINT32                    Offset;
   2971   //
   2972   // Make sure they have not already defined a structure with this name
   2973   //
   2974   for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
   2975     if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {
   2976       PrintErrorMessage (LineNum, StructName, "structure with this name already defined");
   2977       //
   2978       // Fall through and fill in the rest of the structure information. We do
   2979       // this because the structure has already been added to our global list,
   2980       // so will be used elsewhere, so we want it to contain valid fields.
   2981       //
   2982     }
   2983   }
   2984   //
   2985   // Allocate memory for the structure name
   2986   //
   2987   mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);
   2988   strcpy (mLastStructDefinition->Name, StructName);
   2989   //
   2990   // Compute the structure size, and the offsets to each field
   2991   //
   2992   Offset = 0;
   2993   for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
   2994     FieldDef->Offset = Offset;
   2995     Offset += FieldDef->ArrayLength * FieldDef->DataSize;
   2996   }
   2997   mLastStructDefinition->Size = Offset;
   2998   //
   2999   // Go through all the structure we have so far and figure out (if we can)
   3000   // the size of the non-NV storage. We also assume that the first structure
   3001   // definition is the primary/default storage for the VFR form.
   3002   //
   3003   if (mNonNvDataStructSize == 0) {
   3004     for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
   3005       if (StructDef->IsNonNV) {
   3006         mNonNvDataStructSize = StructDef->Size;
   3007         break;
   3008       }
   3009     }
   3010   }
   3011   if (mNvDataStructSize == 0) {
   3012     for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
   3013       if (StructDef->IsNonNV == 0) {
   3014         mNvDataStructSize = StructDef->Size;
   3015         break;
   3016       }
   3017     }
   3018   }
   3019 }
   3020 VOID
   3021 EfiVfrParser::AddStructField (
   3022   INT8    *FieldName,
   3023   INT32   LineNum,
   3024   INT32   DataSize,
   3025   INT32   ArrayLength,
   3026   INT8    IsArray
   3027   )
   3028 /*++
   3029 
   3030 Routine Description:
   3031   We're parsing the VFR structure definition. Add another defined field to
   3032   our definition.
   3033 
   3034 Arguments:
   3035   FieldName   - name of the field in the structure.
   3036   LineNum     - the line number from the input (preprocessor output) file
   3037   DataSize    - the size of the field (1, 2, or 4 bytes)
   3038   ArrayLength - the number of elements (for array)
   3039   IsArray     - non-zero if the field is an array
   3040 
   3041 Returns:
   3042   None.
   3043 
   3044 --*/
   3045 {
   3046   STRUCT_FIELD_DEFINITION *FieldDef;
   3047   STRUCT_FIELD_DEFINITION *Temp;
   3048   //
   3049   // Make sure we don't already have a field of this name in our structure
   3050   //
   3051   for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
   3052     if (strcmp (FieldDef->Name, FieldName) == 0) {
   3053       PrintErrorMessage (LineNum, FieldName, "field with this name already defined");
   3054       return;
   3055     }
   3056   }
   3057   //
   3058   // If it's an array, then they better not have a size of 0. For example:
   3059   //   UINT8 MyBytes[0];
   3060   //
   3061   if (IsArray && (ArrayLength <= 0)) {
   3062     PrintErrorMessage (LineNum, FieldName, "invalid array size");
   3063     return;
   3064   }
   3065   //
   3066   // Allocate memory for a new structure field definition
   3067   //
   3068   FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));
   3069   memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));
   3070   FieldDef->ArrayLength  = ArrayLength;
   3071   FieldDef->DataSize     = DataSize;
   3072   FieldDef->IsArray      = IsArray;
   3073   FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);
   3074   strcpy (FieldDef->Name, FieldName);
   3075   //
   3076   // Add it to the end of the field list for the currently active structure
   3077   //
   3078   if (mLastStructDefinition->Field == NULL) {
   3079     mLastStructDefinition->Field = FieldDef;
   3080   } else {
   3081     mLastStructDefinition->LastField->Next = FieldDef;
   3082   }
   3083   mLastStructDefinition->LastField = FieldDef;
   3084 }
   3085 VOID
   3086 EfiVfrParser::AddVarStore (
   3087   INT8   *StructName,       // actual name of the structure
   3088   INT8   *VarName,          // actual NV variable name
   3089   UINT16 VarStoreId,        // key value
   3090   INT32  LineNum            // parse line number (for error reporting)
   3091   )
   3092 /*++
   3093 
   3094 Routine Description:
   3095   Called while parsing a varstore statement. Add the variable store
   3096   to our linked list.
   3097 
   3098 Arguments:
   3099   StructName    - the name of the typedef'ed structure to use
   3100   VarName       - the NV variable name as specified in the varstore statement
   3101   VarStoreId    - the variable store ID as specified in the varstore statememt
   3102   LineNum       - the line number from the input (preprocessor output) file
   3103 
   3104 Returns:
   3105   None.
   3106 
   3107 --*/
   3108 {
   3109   STRUCT_DEFINITION *StructDef;
   3110   UINT16_LIST       *L16Ptr;
   3111   //
   3112   // Go through our list of previously-defined variable store IDs and
   3113   // make sure this one is not a duplicate in name or key value.
   3114   //
   3115   for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {
   3116     if (L16Ptr->Value == VarStoreId) {
   3117       PrintErrorMessage (LineNum, "variable storage key already used", NULL);
   3118       PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);
   3119     }
   3120   }
   3121   //
   3122   // Key value of 0 is invalid since that's assigned by default to the default
   3123   // variable store (the first structure parsed).
   3124   //
   3125   if (VarStoreId == 0) {
   3126     PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);
   3127   }
   3128   //
   3129   // Create a new element to add to the list
   3130   //
   3131   L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));
   3132   memset (L16Ptr, 0, sizeof (UINT16_LIST));
   3133   L16Ptr->LineNum = LineNum;
   3134   L16Ptr->Value = VarStoreId;
   3135   if (mDefinedVarStoreId == NULL) {
   3136     mDefinedVarStoreId = L16Ptr;
   3137   } else {
   3138     mLastDefinedVarStoreId->Next = L16Ptr;
   3139   }
   3140   mLastDefinedVarStoreId = L16Ptr;
   3141   //
   3142   // Find the structure definition with this name
   3143   //
   3144   for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
   3145     if (strcmp (StructDef->Name, StructName) == 0) {
   3146       //
   3147       // Make sure they did not already define a variable storage ID
   3148       // for this structure.
   3149       //
   3150       if (StructDef->VarStoreId != 0) {
   3151         PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");
   3152         PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");
   3153       }
   3154       StructDef->VarStoreId       = VarStoreId;
   3155       StructDef->VarStoreIdValid  = 1;
   3156       StructDef->VarStoreLineNum  = LineNum;
   3157       WriteWord (StructDef->Size);
   3158       while (*VarName) {
   3159         WriteByte(*VarName, 0);
   3160         VarName++;
   3161       }
   3162       WriteByte(0,0);
   3163       return;
   3164     }
   3165   }
   3166   PrintErrorMessage (LineNum, StructName, "structure with this name not defined");
   3167 }
   3168 VOID
   3169 EfiVfrParser::WriteDWord (
   3170   UINT32    Value,
   3171   UINT8     KeyByte
   3172   )
   3173 /*++
   3174 
   3175 Routine Description:
   3176   During parsing, we came upon some code that requires a 32-bit value be
   3177   written to the VFR binary file. Queue up the 4 bytes.
   3178 
   3179 Arguments:
   3180   Value   - the 32-bit value to write
   3181   KeyByte - a single character which gets written out beside the first byte.
   3182             This is used to tag the data in the output file so that during
   3183             debug you have an idea what the value is.
   3184 
   3185 Returns:
   3186   None.
   3187 
   3188 --*/
   3189 {
   3190   //
   3191   // Write 4 bytes, little endian. Specify a key byte only on the first one
   3192   //
   3193   mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);
   3194   Value \>>= 8;
   3195   mOpcodeHandler.AddByte ((UINT8)Value, 0);
   3196   Value \>>= 8;
   3197   mOpcodeHandler.AddByte ((UINT8)Value, 0);
   3198   Value \>>= 8;
   3199   mOpcodeHandler.AddByte ((UINT8)Value, 0);
   3200 }
   3201 VOID
   3202 EfiVfrParser::WriteOpByte (
   3203   UINT32    LineNum,
   3204   UINT8     ByteValue
   3205   )
   3206 /*++
   3207 
   3208 Routine Description:
   3209 
   3210   During parsing, we came upon a new VFR opcode. At this point we flush
   3211   the output queue and then queue up this byte (with 'O' for opcode tag).
   3212 
   3213 Arguments:
   3214 
   3215   ByteValue   - opcode value
   3216 
   3217 Returns:
   3218 
   3219   None.
   3220 
   3221 --*/
   3222 {
   3223   mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
   3224 }
   3225 VOID
   3226 EfiVfrParser::WriteByte (
   3227   UINT8   ByteValue,
   3228   UINT8   Key
   3229   )
   3230 /*++
   3231 
   3232 Routine Description:
   3233 
   3234   During parsing of the VFR we spoonfeed this function with bytes to write to
   3235   the output VFR binary file. This function simply queues up the bytes, and
   3236   the queue gets flushed each time a new VFR opcode is encountered.
   3237 
   3238 Arguments:
   3239 
   3240   ByteValue   - raw byte to write
   3241   Key         - character to tag the byte with when we write ByteValue to the
   3242                 output file.
   3243 
   3244 Returns:
   3245 
   3246   None.
   3247 
   3248 --*/
   3249 {
   3250   mOpcodeHandler.AddByte (ByteValue, Key);
   3251 }
   3252 VOID
   3253 EfiVfrParser::WriteWord (
   3254   UINT32  Value
   3255   )
   3256 /*++
   3257 
   3258 Routine Description:
   3259   During VFR parsing we came upon a case where we need to write out a
   3260   16-bit value. Queue it up.
   3261 
   3262 Arguments:
   3263   Value - value to write.
   3264 
   3265 Returns:
   3266   None.
   3267 
   3268 --*/
   3269 {
   3270   mOpcodeHandler.AddByte ((UINT8)Value, 0);
   3271   mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
   3272 }
   3273 VOID
   3274 EfiVfrParser::WriteStringIdWord (
   3275   UINT16 WordValue
   3276   )
   3277 {
   3278   mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
   3279   mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
   3280 }
   3281 VOID
   3282 EfiVfrParser::FreeGotoReferences ()
   3283 /*++
   3284 
   3285 Routine Description:
   3286   Called during cleanup to free up the memory we allocated when
   3287   keeping track of VFR goto statements.
   3288 
   3289 Arguments:
   3290   None
   3291 
   3292 Returns:
   3293   None
   3294 
   3295 --*/
   3296 {
   3297   GOTO_REFERENCE  *CurrRef;
   3298   GOTO_REFERENCE  *NextRef;
   3299   FORM_ID_VALUE   *CurrFormId;
   3300   FORM_ID_VALUE   *NextFormId;
   3301   UINT8           Found;
   3302   INT8            Name[20];
   3303 
   3304   //
   3305   // Go through all the "goto" references and make sure there was a
   3306   // form ID of that value defined.
   3307   //
   3308   for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {
   3309     Found = 0;
   3310     for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {
   3311       if (CurrRef->Value == CurrFormId->Value) {
   3312         Found = 1;
   3313         break;
   3314       }
   3315     }
   3316     if (!Found) {
   3317       sprintf (Name, "%d", (UINT32)CurrRef->Value);
   3318       PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");
   3319     }
   3320   }
   3321   //
   3322   // Now free up the form id and goto references
   3323   //
   3324   CurrFormId = mFormIdValues;
   3325   while (CurrFormId != NULL) {
   3326     NextFormId = CurrFormId->Next;
   3327     free (CurrFormId);
   3328     CurrFormId = NextFormId;
   3329   }
   3330   mFormIdValues = NULL;
   3331   CurrRef = mGotoReferences;
   3332   while (CurrRef != NULL) {
   3333     NextRef = CurrRef->Next;
   3334     free (CurrRef);
   3335     CurrRef = NextRef;
   3336   }
   3337   mGotoReferences = NULL;
   3338 }
   3339 VOID
   3340 EfiVfrParser::AddGotoReference (
   3341   UINT32  GotoNumber,
   3342   UINT32  LineNum
   3343   )
   3344 /*++
   3345 
   3346 Routine Description:
   3347   During VFR parsing we came upon a goto statement. Since we support
   3348   forward references, save the referenced label and at the end of parsing
   3349   we'll check that the label was actually defined somewhere.
   3350 
   3351 Arguments:
   3352   GotoNumber  - the label number referenced
   3353   LineNum     - the line number where the reference was made (used for
   3354                 error reporting)
   3355 
   3356 Returns:
   3357   None
   3358 
   3359 --*/
   3360 {
   3361   GOTO_REFERENCE *NewRef;
   3362 
   3363   NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));
   3364   if (NewRef == NULL) {
   3365     Error (UTILITY_NAME, 0, 0, NULL, "memory allocation failure");
   3366     return;
   3367   }
   3368   memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));
   3369   NewRef->Value = (UINT16)GotoNumber;
   3370   NewRef->RefLineNum = LineNum;
   3371   NewRef->Next = mGotoReferences;
   3372   mGotoReferences = NewRef;
   3373 }
   3374 VOID
   3375 EfiVfrParser::AddFormId (
   3376   INT32   FormIdValue,
   3377   UINT32  LineNum
   3378   )
   3379 /*++
   3380 
   3381 Routine Description:
   3382   This function is called when we parse "form formid = 3" statements.
   3383   We save the form ID valud so we can verify that duplicates are not
   3384   defined. Also, these are the targets of goto statements, so when we're
   3385   done parsing the script we also go through all the goto statements to
   3386   check that there was a target FormId defined as referenced by each
   3387   goto statement.
   3388 
   3389   Note that formid = 0 is invalid.
   3390 
   3391 Arguments:
   3392   FormIdValue  - the parsed value for the Form ID
   3393   LineNum      - line number of the source file we're parsing
   3394 
   3395 Returns:
   3396   NA
   3397 
   3398 --*/
   3399 {
   3400   FORM_ID_VALUE *NewFormId;
   3401   char          *FileName;
   3402   char          *FileName2;
   3403   UINT32        LineNum2;
   3404   //
   3405   // Verify that FormId != 0
   3406   //
   3407   if (FormIdValue == 0) {
   3408     FileName = ConvertLineNumber (&LineNum);
   3409     Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);
   3410     return;
   3411   }
   3412   //
   3413   // First go through all previously defined form IDs and make sure they have not defined
   3414   // duplicates.
   3415   //
   3416   for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {
   3417     if ((UINT16)FormIdValue == NewFormId->Value) {
   3418       FileName = ConvertLineNumber (&LineNum);
   3419       LineNum2 = NewFormId->LineNum;
   3420       FileName2 = ConvertLineNumber (&LineNum2);
   3421       Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);
   3422       Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);
   3423       return;
   3424     }
   3425   }
   3426   //
   3427   // Allocate memory for a new one
   3428   //
   3429   NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));
   3430   if (NewFormId == NULL) {
   3431     Error (UTILITY_NAME, 0, 0, NULL, "memory allocation failure");
   3432     return;
   3433   }
   3434   memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));
   3435   NewFormId->LineNum = LineNum;
   3436   NewFormId->Next = mFormIdValues;
   3437   NewFormId->Value = (UINT16)FormIdValue;
   3438   mFormIdValues = NewFormId;
   3439 }
   3440 UINT32
   3441 EfiVfrParser::GetNumber (
   3442   INT8    *NumStr,
   3443   UINT32  LineNum,
   3444   UINT32  NumBytes
   3445   )
   3446 {
   3447   UINT32 Value;
   3448 
   3449   if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {
   3450     AtoX (NumStr + 2, 4, &Value);
   3451   } else {
   3452     Value = (UINT32)atoi (NumStr);
   3453   }
   3454   //
   3455   // Check range
   3456   //
   3457   if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {
   3458     PrintErrorMessage (LineNum, NumStr, "value out of range");
   3459     return 0;
   3460   }
   3461   return Value;
   3462 }
   3463 
   3464 >>
   3465 
   3466 } // end grammar class
   3467 
   3468 
   3469