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