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