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