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