1/*++
2
3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution.  The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14  VfrCompile.g
15
16Abstract:
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
48class DLGLexerVfr : public DLGLexer
49{
50public:
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
72typedef 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
81static
82VOID
83Usage ();
84
85static
86STATUS
87ProcessArgs (
88  int         Argc,
89  char        *Argv[]
90  );
91
92static
93VOID
94Cleanup ();
95
96//
97// Globals
98//
99OPTIONS gOptions;
100
101int
102main (
103  int   argc,
104  char  **argv
105  )
106/*++
107
108Routine Description:
109  Application entry point function. Parse command-line arguments,
110  invoke the parser, clean up, and return.
111
112Arguments:
113  argc - standard argc passed to main() per C conventions
114  argv - standard argv passed to main() per C conventions
115
116Returns:
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}
257static
258VOID
259Cleanup ()
260/*++
261
262Routine Description:
263  Free up memory allocated during parsing.
264
265Arguments:
266  None
267
268Returns:
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
289static
290STATUS
291ProcessArgs (
292  int         Argc,
293  char        *Argv[]
294  )
295/*++
296
297Routine Description:
298  Process the command-line arguments.
299
300Arguments:
301  Argc - standard argc passed to main()
302  Argv - standard argv passed to main()
303
304Returns:
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}
488static
489VOID
490Usage ()
491/*++
492
493Routine Description:
494  Print utility usage instructions
495
496Arguments:
497  None
498
499Returns:
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
540PARSER_LINE_DEFINITION  *gLineDefinition = NULL;
541PARSER_LINE_DEFINITION  *gLastLineDefinition = NULL;
542
543VOID
544AddFileLine (
545  char      *TokenString,
546  UINT32    TokenLine
547  )
548/*++
549
550Routine 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
558Arguments:
559  TokenString - the parsed string as shown above
560  TokenLine   - the line number in the preprocessed output file
561
562Returns:
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}
604char *
605ConvertLineNumber (
606  UINT32 *LineNum
607  )
608/*++
609
610Routine 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
615Arguments:
616  LineNum - the line number in the preprocessor-output file.
617
618Returns:
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//
860program :
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
869formSetStatement :
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//
904classDefinition :
905  validClassNames ( "\|" validClassNames )*
906  ;
907
908validClassNames :
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//
922subclassDefinition :
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//
936dataStructDefinition :
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
951dataStructFields :
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//
963dataStructField64 :
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//
979dataStructField32 :
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//
995dataStructField16 :
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//
1011dataStructField8 :
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//
1029formDefinition :
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//
1042vfrStatements :
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//
1070vfrStatementLabel :
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//
1084vfrStatementOem :
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//
1096vfrStatementInconsistentIf :
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//
1119vfrBooleanExpression :
1120  leftPartVfrBooleanExp { rightPartVfrBooleanExp }
1121  ;
1122
1123leftPartVfrBooleanExp :
1124  OpenParen vfrBooleanExpression CloseParen                                                        |
1125  (ideqval | ideqid | ideqvallist | vareqval | truefalse)                                          |
1126  NOPID:NOT leftPartVfrBooleanExp           << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
1127  ;
1128
1129rightPartVfrBooleanExp :
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//
1139truefalse :
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//
1149vfrStatementVarStore :
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//
1183vareqval :
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
1191ideqval :
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//
1205ideqid :
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//
1215compareNumber :
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//
1248compareVfrStructFieldNameNL0 :
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
1278ideqvallist :
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
1286vfrStatementGoto :
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
1305vfrStatementHidden :
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//
1324vfrStatementSuppressIf :
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//
1340suppressIfGrayOutIf :
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//
1360vfrStatementGrayOutIf :
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//
1376grayoutIfSuppressIf :
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//
1390suppressIfAndGrayoutIfSubstatements :
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
1419vfrStatementPassword :
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//
1454vfrStatementString :
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//
1491vfrStatementNumeric :
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//
1514minMaxStepDefault :
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//
1553vfrStatementDate :
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
1567vfrStatementTime :
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//
1589vfrStatementTextText :
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//
1610vfrStatementInventory :
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//
1637vfrStatementSaveRestoreDefaults :
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//
1665flagsField :
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
1675dateTimeSubStatement :
1676  Prompt  "=" getStringId ","
1677  Help    "=" getStringId ","
1678                                      << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
1679  minMaxStepDefault                   << WriteMinMaxStepDefault (); >>
1680  ;
1681
1682vfrStatementCheckBox :
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
1696vfrStatementSubTitle :
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//
1713vfrStatementBanner :
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//
1743vfrStatementOneOf :
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//
1764vfrStatementOrderedList :
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//
1783orderedListOptionText :
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//
1811orderedListFlagsField :
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//
1828vfrStructFieldNameArray[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//
1852vfrStructFieldName[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//
1881vfrStructFieldNameNL[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//
1910oneOfOptionText :
1911  suppressIfOptionText    |
1912  grayOutIfOptionText     |
1913  commonOptionText
1914  ;
1915
1916suppressIfOptionText :
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
1929grayOutIfOptionText :
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
1942commonOptionText :
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//
1960getStringId :
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//
1971class EfiVfrParser {
1972<<
1973//
1974// Parser definitions go here
1975//
1976private:
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;
2006public:
2007
2008VOID
2009EfiVfrParser::SetIfStart (
2010  UINT32 LineNum
2011  )
2012/*++
2013
2014Routine 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
2019Arguments:
2020  LineNum - source line number where the "if" was parsed.
2021
2022Returns:
2023  None
2024
2025--*/
2026{
2027  mIfStart = LineNum;
2028}
2029VOID
2030EfiVfrParser::SetClass (
2031  UINT32 LineNum,
2032  UINT32 Value
2033  )
2034/*++
2035
2036Routine 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
2040Arguments:
2041  LineNum - source line number where the class statement was parsed.
2042  Value   - the class value
2043
2044Returns:
2045  None
2046
2047--*/
2048{
2049  if (Value & 0xFFFF0000) {
2050    PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
2051  }
2052  mClass |= (UINT16)Value;
2053}
2054VOID
2055EfiVfrParser::SetSubclass (
2056  UINT32 LineNum,
2057  UINT32 Value
2058  )
2059/*++
2060
2061Routine 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
2065Arguments:
2066  LineNum - source line number where the class statement was parsed.
2067  Value   - the subclass value from the VFR statement
2068
2069Returns:
2070  None
2071
2072--*/
2073{
2074  if (Value & 0xFFFF0000) {
2075    PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
2076  }
2077  mSubclass |= (UINT16)Value;
2078}
2079VOID EfiVfrParser::WriteClass ()
2080{
2081  WriteWord (mClass);
2082  mClass = 0;
2083}
2084VOID EfiVfrParser::WriteSubclass ()
2085{
2086  WriteWord (mSubclass);
2087  mSubclass = 0;
2088}
2089VOID EfiVfrParser::WriteIfrBytes ()
2090{
2091  mOpcodeHandler.WriteIfrBytes ();
2092}
2093VOID
2094EfiVfrParser::WriteFlagsKey (
2095  UINT32 KeyValue,
2096  UINT32 LineNum
2097  )
2098/*++
2099
2100Routine 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
2107Arguments:
2108  KeyValue  - the key value from the VFR statement
2109  LineNum   - source line number where the statement was parsed
2110
2111Returns:
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}
2126VOID
2127EfiVfrParser::InitOrderedList ()
2128{
2129  mOptionCount = 0;
2130}
2131VOID
2132EfiVfrParser::EndOrderedList (
2133  UINT32 LineNum
2134  )
2135{
2136  if (mLastVarIdSize < mOptionCount) {
2137    PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
2138  }
2139}
2140VOID
2141EfiVfrParser::ResetFlags ()
2142/*++
2143
2144Routine 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
2152Arguments:
2153  None
2154
2155Returns:
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//
2167VOID
2168EfiVfrParser::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}
2179VOID
2180EfiVfrParser::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}
2197VOID
2198EfiVfrParser::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//
2222VOID
2223EfiVfrParser::InitMinMaxStepDefault ()
2224{
2225  mMinimumValue         = 0;
2226  mMaximumValue         = 0;
2227  mStepValue            = 1;
2228  mDefaultValue         = 0;
2229}
2230VOID
2231EfiVfrParser::WriteMinMaxStepDefault ()
2232{
2233  WriteWord (mMinimumValue);
2234  WriteWord (mMaximumValue);
2235  WriteWord (mStepValue);
2236  WriteWord (mDefaultValue);
2237}
2238VOID
2239EfiVfrParser::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}
2287VOID
2288EfiVfrParser::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}
2317VOID
2318EfiVfrParser::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}
2338VOID
2339EfiVfrParser::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}
2373VOID
2374EfiVfrParser::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}
2389VOID
2390EfiVfrParser::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}
2405VOID
2406EfiVfrParser::syn (
2407  ANTLRAbstractToken  *Tok,
2408  ANTLRChar           *Egroup,
2409  SetWordType         *Eset,
2410  ANTLRTokenType      ETok,
2411  INT32               Huh
2412  )
2413/*++
2414
2415Routine Description:
2416  Called by the parser base class as a result of parse syntax errors.
2417
2418Arguments:
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
2424Returns:
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
2455VOID
2456EfiVfrParser::init()
2457/*++
2458
2459Routine Description:
2460  Initializations function for our parser.
2461
2462Arguments:
2463  None.
2464
2465Returns:
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//
2498EfiVfrParser::~EfiVfrParser(VOID)
2499{
2500  Cleanup();
2501}
2502VOID
2503EfiVfrParser::Cleanup (VOID)
2504/*++
2505
2506Routine Description:
2507  Free memory allocated during parsing
2508
2509Arguments:
2510  None.
2511
2512Returns:
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
2562INT32
2563EfiVfrParser::AtoX (
2564  INT8    *HexString,
2565  INT32   NumBytes,
2566  UINT32  *HexValue
2567  )
2568/*++
2569
2570Routine Description:
2571  Given a pointer to a ascii hex string, convert to a number with the given
2572  number of bytes.
2573
2574Arguments:
2575  HexString   - pointer to a string of format 30BCA
2576  Size        - number of bytes to convert
2577  HexValue    - return result
2578
2579Returns:
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}
2616VOID
2617EfiVfrParser::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
2633Routine 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
2639Arguments:
2640  TokenLineNum   - line number where the guid was used
2641  G1-G11         - the 11 fields of the guid value
2642
2643Returns:
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}
2676VOID
2677EfiVfrParser::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
2690Routine 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
2694Arguments:
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
2705Returns:
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}
2919VOID
2920EfiVfrParser::StartStructDefinition (
2921  INT32  IsNonNV,
2922  INT32  LineNum
2923  )
2924/*++
2925
2926Routine 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
2930Arguments:
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.
2934Returns:
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}
2962VOID
2963EfiVfrParser::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}
3020VOID
3021EfiVfrParser::AddStructField (
3022  INT8    *FieldName,
3023  INT32   LineNum,
3024  INT32   DataSize,
3025  INT32   ArrayLength,
3026  INT8    IsArray
3027  )
3028/*++
3029
3030Routine Description:
3031  We're parsing the VFR structure definition. Add another defined field to
3032  our definition.
3033
3034Arguments:
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
3041Returns:
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}
3085VOID
3086EfiVfrParser::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
3094Routine Description:
3095  Called while parsing a varstore statement. Add the variable store
3096  to our linked list.
3097
3098Arguments:
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
3104Returns:
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}
3168VOID
3169EfiVfrParser::WriteDWord (
3170  UINT32    Value,
3171  UINT8     KeyByte
3172  )
3173/*++
3174
3175Routine 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
3179Arguments:
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
3185Returns:
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}
3201VOID
3202EfiVfrParser::WriteOpByte (
3203  UINT32    LineNum,
3204  UINT8     ByteValue
3205  )
3206/*++
3207
3208Routine 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
3213Arguments:
3214
3215  ByteValue   - opcode value
3216
3217Returns:
3218
3219  None.
3220
3221--*/
3222{
3223  mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
3224}
3225VOID
3226EfiVfrParser::WriteByte (
3227  UINT8   ByteValue,
3228  UINT8   Key
3229  )
3230/*++
3231
3232Routine 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
3238Arguments:
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
3244Returns:
3245
3246  None.
3247
3248--*/
3249{
3250  mOpcodeHandler.AddByte (ByteValue, Key);
3251}
3252VOID
3253EfiVfrParser::WriteWord (
3254  UINT32  Value
3255  )
3256/*++
3257
3258Routine 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
3262Arguments:
3263  Value - value to write.
3264
3265Returns:
3266  None.
3267
3268--*/
3269{
3270  mOpcodeHandler.AddByte ((UINT8)Value, 0);
3271  mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
3272}
3273VOID
3274EfiVfrParser::WriteStringIdWord (
3275  UINT16 WordValue
3276  )
3277{
3278  mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
3279  mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
3280}
3281VOID
3282EfiVfrParser::FreeGotoReferences ()
3283/*++
3284
3285Routine Description:
3286  Called during cleanup to free up the memory we allocated when
3287  keeping track of VFR goto statements.
3288
3289Arguments:
3290  None
3291
3292Returns:
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}
3339VOID
3340EfiVfrParser::AddGotoReference (
3341  UINT32  GotoNumber,
3342  UINT32  LineNum
3343  )
3344/*++
3345
3346Routine 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
3351Arguments:
3352  GotoNumber  - the label number referenced
3353  LineNum     - the line number where the reference was made (used for
3354                error reporting)
3355
3356Returns:
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}
3374VOID
3375EfiVfrParser::AddFormId (
3376  INT32   FormIdValue,
3377  UINT32  LineNum
3378  )
3379/*++
3380
3381Routine 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
3391Arguments:
3392  FormIdValue  - the parsed value for the Form ID
3393  LineNum      - line number of the source file we're parsing
3394
3395Returns:
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}
3440UINT32
3441EfiVfrParser::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