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