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