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