3 Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
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.
18 PCCTS parser and lexer definitions for the EFI VFR forms compiler
25 #include "EfiUtilityMsgs.h"
27 #include "VfrServices.h"
28 #include EFI_PROTOCOL_DEFINITION (Hii)
32 #include <process.h> // for spawn functions
39 // Base info for DLG-generated scanner
41 #include "DLexerBase.h"
44 // Include the scanner file generated by DLG
48 class DLGLexerVfr : public DLGLexer
51 DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};
52 INT32 errstd (char *Text)
54 printf ("unrecognized input '%s'\n", Text);
59 // Base token definitions for ANTLR
64 // This is how we invoke the C preprocessor on the VFR source file
65 // to resolve #defines, #includes, etc. To make C source files
66 // shareable between VFR and drivers, define VFRCOMPILE so that
67 // #ifdefs can be used in shared .h files.
69 #define PREPROCESSOR_COMMAND "cl.exe "
70 #define PREPROCESSOR_OPTIONS "/nologo /E /TC /DVFRCOMPILE "
72 typedef ANTLRCommonToken ANTLRToken;
75 // Specify the filename extensions for the files we generate.
77 #define VFR_BINARY_FILENAME_EXTENSION ".c"
78 #define VFR_LIST_FILENAME_EXTENSION ".lst"
79 #define VFR_PREPROCESS_FILENAME_EXTENSION ".i"
109 Application entry point function. Parse command-line arguments,
110 invoke the parser, clean up, and return.
113 argc - standard argc passed to main() per C conventions
114 argv - standard argv passed to main() per C conventions
117 STATUS_SUCCESS - program executed with no errors or warnings
118 STATUS_WARNING - program executed with warnings
119 STATUS_ERROR - non-recoverable errors encountered while processing
130 // Set our program name for the error printing routines.
131 // Then set printing limits.
133 SetUtilityName (PROGRAM_NAME);
134 SetPrintLimits (20, 20, 30);
136 // Process the command-line arguments
138 if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {
145 // Verify the VFR script file exists
147 if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {
148 Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");
153 // Now close the file and make a system call to run the preprocessor
157 Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10 +
158 strlen (PREPROCESSOR_COMMAND) + strlen (gOptions.PreprocessorOutputFileName);
159 if (gOptions.CPreprocessorOptions != NULL) {
160 Len += strlen (gOptions.CPreprocessorOptions) + 1;
162 if (gOptions.IncludePaths != NULL) {
163 Len += strlen (gOptions.IncludePaths) + 1;
165 Cmd = (char *)malloc (Len);
167 Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");
171 strcpy (Cmd, PREPROCESSOR_COMMAND PREPROCESSOR_OPTIONS);
172 if (gOptions.IncludePaths != NULL) {
173 strcat (Cmd, gOptions.IncludePaths);
176 if (gOptions.CPreprocessorOptions != NULL) {
177 strcat (Cmd, gOptions.CPreprocessorOptions);
180 strcat (Cmd, gOptions.VfrFileName);
182 strcat (Cmd, gOptions.PreprocessorOutputFileName);
183 Status = system (Cmd);
185 Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");
186 printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);
192 // Open the preprocessor output file
194 if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
195 Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file",
196 gOptions.PreprocessorOutputFileName);
201 // Define input VFR file
203 DLGFileInput InputFile (VfrFptr);
205 // Define an instance of the scanner
207 DLGLexerVfr Scanner (&InputFile);
209 // Define token buffer between scanner and parser
211 ANTLRTokenBuffer Pipe (&Scanner);
213 // Create a token to use as a model
217 // Tell the scanner what type the token is
219 Scanner.setToken (&Tok);
221 // Create an instance of our parser
223 EfiVfrParser Parser (&Pipe);
225 // Initialize the parser
228 Status = GetUtilityStatus ();
229 if (Status != STATUS_SUCCESS) {
234 // Start the first rule
238 // Close the input script file
241 Parser.WriteIfrBytes ();
243 // Call cleanup, which does some extra checking of the script
248 // If we had an error somewhere, delete our output files so that
249 // a subsequent build will rebuild them.
251 Status = GetUtilityStatus ();
252 if (Status == STATUS_ERROR) {
253 remove (gOptions.IfrOutputFileName);
263 Free up memory allocated during parsing.
274 // Free up our string we allocated to track the include paths
276 if (gOptions.IncludePaths != NULL) {
277 free (gOptions.IncludePaths);
278 gOptions.IncludePaths = NULL;
281 // Free up our string we allocated to track preprocessor options
283 if (gOptions.CPreprocessorOptions != NULL) {
284 free (gOptions.CPreprocessorOptions);
285 gOptions.CPreprocessorOptions = NULL;
298 Process the command-line arguments.
301 Argc - standard argc passed to main()
302 Argv - standard argv passed to main()
305 STATUS_SUCCESS - program should continue (all args ok)
310 char *CPreprocessorOptions;
312 char CopyStr[MAX_PATH];
316 // Put options in known state.
318 memset ((char *)&gOptions, 0, sizeof (OPTIONS));
320 // Go through all the arguments that start with '-'
324 while ((Argc > 0) && (Argv[0][0] == '-')) {
326 // -? or -h help option -- return an error for printing usage
328 if ((_stricmp (Argv[0], "-?") == 0) || (_stricmp (Argv[0], "-h") == 0)) {
332 // -l to create a listing output file
334 } else if (_stricmp (Argv[0], "-l") == 0) {
335 gOptions.CreateListFile = 1;
337 // -I include_path option for finding include files. We'll pass this
338 // to the preprocessor. Turn them all into a single include string.
340 } else if (_stricmp (Argv[0], "-i") == 0) {
341 if ((Argc < 2) || (Argv[1][0] == '-')) {
342 Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument");
347 Len = strlen (" -I ");
348 Len += strlen (Argv[0]) + 2;
349 if (gOptions.IncludePaths != NULL) {
350 Len += strlen (gOptions.IncludePaths);
352 IncludePaths = (INT8 *)malloc (Len);
353 if (IncludePaths == NULL) {
354 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
358 if (gOptions.IncludePaths != NULL) {
359 strcpy (IncludePaths, gOptions.IncludePaths);
360 free (gOptions.IncludePaths);
362 strcat (IncludePaths, " -I ");
363 strcat (IncludePaths, Argv[0]);
364 gOptions.IncludePaths = IncludePaths;
366 // -od OutputDirectory to define a common directory for output files
368 } else if (_stricmp (Argv[0], "-od") == 0) {
369 if ((Argc < 2) || (Argv[1][0] == '-')) {
370 Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");
375 strcpy (gOptions.OutputDirectory, Argv[0]);
376 } else if (_stricmp (Argv[0], "-ibin") == 0) {
377 gOptions.CreateIfrBinFile = 1;
378 } else if (_stricmp (Argv[0], "-nostrings") == 0) {
381 // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
382 // Turn them all into a single string.
384 } else if (_stricmp (Argv[0], "-ppflag") == 0) {
386 Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
391 Len = strlen (Argv[0]) + 2;
392 if (gOptions.CPreprocessorOptions != NULL) {
393 Len += strlen (gOptions.CPreprocessorOptions);
395 CPreprocessorOptions = (INT8 *)malloc (Len);
396 if (CPreprocessorOptions == NULL) {
397 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
400 CPreprocessorOptions[0] = 0;
401 if (gOptions.CPreprocessorOptions != NULL) {
402 strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
403 free (gOptions.CPreprocessorOptions);
405 strcat (CPreprocessorOptions, " ");
406 strcat (CPreprocessorOptions, Argv[0]);
407 gOptions.CPreprocessorOptions = CPreprocessorOptions;
409 Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
416 // Must specify at least the vfr file name
419 Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
421 } else if (Argc < 1) {
422 Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");
425 strcpy (gOptions.VfrFileName, Argv[0]);
427 strcpy (CopyStr, gOptions.VfrFileName);
428 Cptr = CopyStr + strlen (CopyStr) - 1;
429 for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':'); Cptr--);
430 if (Cptr == CopyStr) {
431 strcpy (gOptions.VfrBaseFileName, Cptr);
433 strcpy (gOptions.VfrBaseFileName, Cptr+1);
436 // Terminate the vfr file basename at the extension
438 for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
442 // If they defined an output directory, prepend all output files
443 // with the working directory. Output files of interest:
444 // VfrListFileName -- list file
445 // IfrOutputFileName -- IFR bytes
446 // StringOutputFileName -- string bytes
447 // StringListFileName -- not used
448 // StringDefineFileName -- #defines of string identifiers
450 // We have two cases:
451 // 1. Output directory (-od) not specified, in which case output files
452 // go to the current working directory.
453 // 2. Output directory specified, in which case the output files
454 // go directly to the specified directory.
456 if (gOptions.OutputDirectory[0] == 0) {
458 _getcwd (CopyStr, sizeof (CopyStr));
459 strcpy (gOptions.OutputDirectory, CopyStr);
462 // Make sure output directory has a trailing backslash
464 if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\') {
465 strcat (gOptions.OutputDirectory, "\\");
468 // Create the base output file name as: path\base, copy it to all the output
469 // filenames, and then add the appropriate extension to each.
471 strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);
472 strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);
473 strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);
474 strcpy (gOptions.PreprocessorOutputFileName, gOptions.VfrListFileName);
475 strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);
476 strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);
477 strcat (gOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
480 // We set a default list file name, so if they do not
481 // want a list file, null out the name now.
483 if (gOptions.CreateListFile == 0) {
484 gOptions.VfrListFileName[0] = 0;
486 return STATUS_SUCCESS;
494 Print utility usage instructions
505 const char *Help[] = {
507 "VfrCompile version " VFR_COMPILER_VERSION,
509 " Usage: VfrCompile {options} [VfrFile]",
511 " where options include:",
512 " -? or -h prints this help",
513 " -l create an output IFR listing file",
514 " -i IncPath add IncPath to the search path for VFR included files",
515 " -od OutputDir deposit all output files to directory OutputDir (default=cwd)",
516 " -ibin create an IFR HII pack file",
517 " where parameters include:",
518 " VfrFile name of the input VFR script file",
522 for (Index = 0; Help[Index] != NULL; Index++) {
523 fprintf (stdout, "%s\n", Help[Index]);
535 PARSER_LINE_DEFINITION *gLineDefinition = NULL;
536 PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;
546 During the lexer phase, if we encounter a #line statement output by
547 the preprocessor, this function gets called. We'll save off the info
548 for error reporting purposes. The preprocessor line information has the
554 TokenString - the parsed string as shown above
555 TokenLine - the line number in the preprocessed output file
562 PARSER_LINE_DEFINITION *LineDef;
566 // Allocate a structure in which we can keep track of this line information.
568 LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));
569 memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));
570 LineDef->TokenLineNum = TokenLine;
571 LineDef->HashLineNum = atoi (TokenString + 6);
573 // Find the quotes in the filename, then allocate space in the line
574 // def structure for a copy of the filename. Finally, copy it without
575 // quotes to the line def.
577 for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
579 LineDef->FileName = (INT8 *)malloc (strlen (Cptr));
581 strcpy (LineDef->FileName, Cptr);
582 for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
585 // Now add this new one to the list
587 if (gLineDefinition == NULL) {
588 gLineDefinition = LineDef;
590 gLastLineDefinition->Next = LineDef;
592 gLastLineDefinition = LineDef;
594 Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
606 Given the line number in the preprocessor-output file, use the line number
607 information we've saved to determine the source file name and line number
608 where the code originally came from. This is required for error reporting.
611 LineNum - the line number in the preprocessor-output file.
614 Returns a pointer to the source file name. Also returns the line number
615 in the provided LineNum argument
619 PARSER_LINE_DEFINITION *LineDef;
621 // Step through our linked list of #line information we saved off.
622 // For each one, look at its line number, and the line number of the
623 // next record, and see if the passed-in line number is in the range.
624 // If it is, then convert the line number to the appropriate line number
625 // of the original source file.
627 for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
629 // The given LineNum is the line number from the .i file.
630 // Find a line definition whose range includes this line number,
631 // convert the line number, and return the filename.
633 if (LineDef->TokenLineNum <= *LineNum) {
634 if (LineDef->Next != NULL) {
635 if (LineDef->Next->TokenLineNum > *LineNum) {
636 *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
637 return LineDef->FileName;
641 // Last one in the list of line definitions, so has to be right
643 *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
644 return LineDef->FileName;
654 // Define a lexical class for parsing quoted strings. Basically
655 // starts with a double quote, and ends with a double quote that
656 // is not preceeded with a backslash.
658 #lexclass QUOTED_STRING
659 #token TheString "~[\"]*\"" << mode (START); >>
662 // Define a lexical class for parsing "#pragma pack" statements.
663 // We do this just for convenience (since we skip them here) so
664 // that users can include some minimal .h files.
666 #lexclass PRAGMA_PACK
667 #token "pack" << skip (); >>
668 #token "[\ \t]" << skip (); >>
669 #token "\(" << skip (); >>
670 #token "[0-9]*" << skip (); >>
671 #token "\)" << skip (); mode (START); >>
674 // Define a lexclass for skipping over C++ style comments
676 #lexclass CPP_COMMENT
677 #token "~[\n]*" << skip (); >>
678 #token "\n" << skip (); mode (START); newline (); >>
681 // Standard lexclass is START
686 // Find start of C++ style comments
688 #token "//" << skip (); mode (CPP_COMMENT); >>
693 #token "[\ \t]" << skip (); >>
696 // Skip over newlines, but count them
698 #token "\n" << skip (); newline (); >>
701 // Skip pragma pack statements
703 #token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
706 // Skip over 'extern' in any included .H file
708 #token "extern" << skip (); >>
711 // Tokens for the different keywords. Syntax is:
712 // TokenName("ErrorMessageText") "TokenString"
714 // TokenName is the token name (must be capitalized) that is used in the rules
715 // ErrorMessageText is the string the compiler emits when it detects a syntax error
716 // TokenString is the actual matching string used in the user script
718 #token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>
719 #token FormSet("formset") "formset"
720 #token EndFormSet("endformset") "endformset"
721 #token Title("title") "title"
722 #token FormId("formid") "formid"
723 #token OneOf("oneof") "oneof"
724 #token Prompt("prompt") "prompt"
725 #token OrderedList("orderedlist") "orderedlist"
726 #token EndList("endlist") "endlist"
727 #token EndForm("endform") "endform"
728 #token EndOneOf("endoneof") "endoneof"
729 #token Form("form") "form"
730 #token Subtitle("subtitle") "subtitle"
731 #token Help("help") "help"
732 #token VarId("varid") "varid"
733 #token Text("text") "text"
734 #token Option("option") "option"
735 #token Value("value") "value"
736 #token Flags("flags") "flags"
737 #token Date("date") "date"
738 #token EndDate("enddate") "enddate"
739 #token Year("year") "year"
740 #token Month("month") "month"
741 #token Day("day") "day"
742 #token Time("time") "time"
743 #token EndTime("endtime") "endtime"
744 #token Hour("hour") "hour"
745 #token Minute("minute") "minute"
746 #token Second("second") "second"
747 #token AND("AND") "AND"
749 #token GrayOutIf("grayoutif") "grayoutif"
750 #token NOT("NOT") "NOT"
751 #token Label("label") "label"
752 #token Timeout("timeout") "timeout"
753 #token Inventory("inventory") "inventory"
754 #token StringToken("STRING_TOKEN") "STRING_TOKEN"
755 #token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP"
756 #token Struct("struct") "struct"
757 #token Uint64("UINT64") "UINT64"
758 #token Uint32("UINT32") "UINT32"
759 #token Uint16("UINT16") "UINT16"
760 #token Char16("CHAR16") "CHAR16"
761 #token Uint8("UINT8") "UINT8"
762 #token Guid("guid") "guid"
763 #token CheckBox("checkbox") "checkbox"
764 #token EndCheckBox("endcheckbox") "endcheckbox"
765 #token Numeric("numeric") "numeric"
766 #token EndNumeric("endnumeric") "endnumeric"
767 #token Minimum("minimum") "minimum"
768 #token Maximum("maximum") "maximum"
769 #token Step("step") "step"
770 #token Default("default") "default"
771 #token Password("password") "password"
772 #token EndPassword("endpassword") "endpassword"
773 #token String("string") "string"
774 #token EndString("endstring") "endstring"
775 #token MinSize("minsize") "minsize"
776 #token MaxSize("maxsize") "maxsize"
777 #token Encoding("encoding") "encoding"
778 #token SuppressIf("suppressif") "suppressif"
779 #token Hidden("hidden") "hidden"
780 #token Goto("goto") "goto"
781 #token InconsistentIf "inconsistentif"
782 #token EndIf("endif") "endif"
783 #token IdEqId("ideqid") "ideqid"
784 #token IdEqVal("ideqval") "ideqval"
785 #token VarEqVal("vareqval") "vareqval"
786 #token Var("var") "var"
787 #token IdEqValList("ideqvallist") "ideqvallist"
788 #token Length("length") "length"
789 #token Values("values") "values"
790 #token Key("key") "key"
791 #token DefaultFlag("DEFAULT") "DEFAULT"
792 #token ManufacturingFlag("MANUFACTURING") "MANUFACTURING"
793 #token InteractiveFlag("INTERACTIVE") "INTERACTIVE"
794 #token NVAccessFlag("NV_ACCESS") "NV_ACCESS"
795 #token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED"
796 #token LateCheckFlag("LATE_CHECK") "LATE_CHECK"
797 #token Class("class") "class"
798 #token Subclass("subclass") "subclass"
799 #token TypeDef("typedef") "typedef"
800 #token Restore("restore") "restore"
801 #token Save("save") "save"
802 #token Defaults("defaults") "defaults"
803 #token Banner("banner") "banner"
804 #token Align("align") "align"
805 #token Left("left") "left"
806 #token Right("right") "right"
807 #token Center("center") "center"
808 #token Line("line") "line"
809 #token VarStore("varstore") "varstore"
810 #token Name("name") "name"
811 #token Oem("oem") "oem"
812 #token True("TRUE") "TRUE"
813 #token False("FALSE") "FALSE"
814 #token GreaterThan(">") ">"
815 #token GreaterEqual(">=") ">="
816 #token LessThan("<") "<"
817 #token LessEqual("<=") "<="
820 // Define the class and subclass tokens
822 #token ClassNonDevice("NONDEVICE") "NON_DEVICE"
823 #token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE"
824 #token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE"
825 #token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE"
826 #token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE"
827 #token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE"
828 #token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE"
830 #token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION"
831 #token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION"
832 #token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE"
833 #token SubclassSingleUse("SINGLE_USE") "SINGLE_USE"
835 #token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters
836 #token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*"
837 #token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+"
838 #token OpenBrace("{") "\{"
839 #token CloseBrace("}") "\}"
840 #token OpenParen("(") "\("
841 #token CloseParen(")") "\)"
842 #token OpenBracket("[") "\["
843 #token CloseBracket("]") "\]"
846 // Define all other invalid characters so that they get through the lexical phase
847 // and we can catch them during the parse phase. We get much better error
850 #token InvalidCharacters("invalid characters") "~[;:=,\.\|]"
853 // This is the overall definition of a VFR form definition script.
856 ( dataStructDefinition )*
858 ( vfrStatementVarStore )*
860 EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>
865 FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>
879 CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
880 G4->getText (), G5->getText (), G6->getText (), G7->getText (),
881 G8->getText (), G9->getText (), G10->getText (), G11->getText ()
885 Title "=" getStringId ","
886 Help "=" getStringId ","
888 // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)
890 << WriteDWord (0, 0); WriteDWord (0, 0); >>
891 Class "=" CVAL:classDefinition "," << WriteClass (); >>
892 Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >>
893 << WriteWord (mNvDataStructSize); >>
897 // A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C
900 validClassNames ( "\|" validClassNames )*
904 CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>
905 | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>
906 | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>
907 | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>
908 | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>
909 | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>
910 | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>
911 | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>
912 ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>
915 // A form can only be of one subclass type.
918 SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>
919 | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>
920 | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>
921 | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>
922 | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>
923 ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>
926 // Parse a C type data structure for storing VFR setup data. Allow:
927 // typedef struct _XXX_ {
931 dataStructDefinition :
932 << int IsNonNV = 0; >>
936 NonNvDataMap << IsNonNV = 1; >>
939 ) << StartStructDefinition (IsNonNV, S->getLine()); >>
942 CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >>
947 ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *
950 //*****************************************************************************
956 // Used while parsing the NV data map structures.
959 << int ArrayLength = 1; char IsArray = 0; >>
961 NAME:StringIdentifier
962 ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
963 << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>
966 //*****************************************************************************
972 // Used while parsing the NV data map structures.
975 << int ArrayLength = 1; char IsArray = 0; >>
977 NAME:StringIdentifier
978 ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
979 << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>
982 //*****************************************************************************
988 // Used while parsing the NV data map structures.
991 << int ArrayLength = 1; char IsArray = 0; >>
992 ( "UINT16" | "CHAR16" )
993 NAME:StringIdentifier
994 ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
995 << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>
998 //*****************************************************************************
1004 // Used while parsing the NV data map structures.
1007 << int ArrayLength = 1; char IsArray = 0; >>
1009 NAME:StringIdentifier
1010 ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
1011 << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>
1014 //*****************************************************************************
1018 // title = STRING_TOKEN(STR_FORM_TITLE);
1019 // -- form statements --
1022 // The Form ID cannot be 0
1025 FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >>
1027 VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>
1029 Title "=" getStringId ";" // writes string identifier
1031 ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>
1035 // VFR statements in a formset
1038 vfrStatementSubTitle |
1040 vfrStatementTextText |
1041 vfrStatementCheckBox |
1042 vfrStatementNumeric |
1045 vfrStatementPassword |
1046 vfrStatementString |
1047 vfrStatementSuppressIf |
1048 vfrStatementHidden |
1050 vfrStatementGrayOutIf |
1051 vfrStatementInconsistentIf |
1053 vfrStatementBanner |
1054 vfrStatementInventory |
1055 vfrStatementOrderedList |
1057 vfrStatementSaveRestoreDefaults
1060 //*****************************************************************************
1066 OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>
1068 WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
1069 AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
1074 //*****************************************************************************
1077 // oem 0x12, 0x34, 0x56;
1080 OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>
1081 ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )
1082 ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*
1086 //*****************************************************************************
1089 // inconsistentif NOT .... AND NOT .... OR ... endif;
1091 vfrStatementInconsistentIf :
1092 << ResetFlags (); >>
1093 IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>
1094 Prompt "=" getStringId ","
1096 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1098 << WriteFlags (); >> // write the flags field
1099 vfrBooleanExpression
1100 EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>
1103 //*****************************************************************************
1106 // TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR
1107 // ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND
1108 // (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR
1109 // vareqval var(VAR_EQ_TEST_NAME) == 0x1)
1111 // For supporting complex express, divide the vfrBooleanExpression to two parts
1112 // so that pred-LL(k) parser can parse incrementally.
1114 vfrBooleanExpression :
1115 leftPartVfrBooleanExp { rightPartVfrBooleanExp }
1118 leftPartVfrBooleanExp :
1119 OpenParen vfrBooleanExpression CloseParen |
1120 (ideqval | ideqid | ideqvallist | vareqval | truefalse) |
1121 NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
1124 rightPartVfrBooleanExp :
1125 AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> |
1126 OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>
1129 //*****************************************************************************
1135 TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |
1136 FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>
1139 //*****************************************************************************
1142 // varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};
1144 vfrStatementVarStore :
1145 OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>
1146 STRUCT_NAME:StringIdentifier ","
1147 Key "=" KNUM:Number ","
1148 Name "=" VAR_NAME:StringIdentifier ","
1162 CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
1163 G4->getText (), G5->getText (), G6->getText (), G7->getText (),
1164 G8->getText (), G9->getText (), G10->getText (), G11->getText ()
1166 WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2));
1167 AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());
1173 //*****************************************************************************
1176 // vareqval var(0x100) == 0x20
1179 OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>
1181 VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>
1187 OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>
1188 vfrStructFieldName[0]
1192 //*****************************************************************************
1195 // ideqid MyNVData3.Field16A == MyNVData3.Field16B
1197 // NOTE: Before processing the second variable store in the ideqid statement, set a global flag
1198 // so that when we parse the second variable we set the secondary variable store id.
1201 OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >>
1202 vfrStructFieldName[0]
1203 compareVfrStructFieldNameNL0
1206 //*****************************************************************************
1208 // compareNumber is the combination of compare operation and Number
1213 VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>
1217 VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));
1218 WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
1222 VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));
1223 WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
1227 VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));
1228 WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
1229 WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
1233 VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));
1234 WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
1235 WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
1239 //*****************************************************************************
1241 // compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0]
1243 compareVfrStructFieldNameNL0 :
1245 "==" << mIdEqIdStmt = 1; >>
1246 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >>
1249 GTOPID:GreaterThan << mIdEqIdStmt = 1; >>
1250 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1251 WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
1254 GEOPID:GreaterEqual << mIdEqIdStmt = 1; >>
1255 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1256 WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
1259 LTOPID:LessThan << mIdEqIdStmt = 1; >>
1260 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1261 WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
1262 WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
1265 LEOPID:LessEqual << mIdEqIdStmt = 1; >>
1266 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1267 WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
1268 WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
1274 OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>
1275 vfrStructFieldName[0]
1277 ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +
1278 << FlushQueueIdEqValList(); >>
1282 << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
1283 IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>
1284 VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
1285 AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
1287 KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >>
1288 Help "=" getStringId
1291 FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1294 "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1296 << WriteFlagsKey (KeyValue, LineNum); >>
1300 vfrStatementHidden :
1301 IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>
1303 VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>
1305 KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>
1309 //*****************************************************************************
1312 // suppressif <boolean_expression> { grayoutif } <statements>+ endif;
1314 // You can have: suppressif:grayoutif:statements:endif
1315 // suppressif:grayoutif:endif -- serves no purpose
1316 // suppressif:statements:endif
1317 // suppressif:endif -- serves no purpose
1319 vfrStatementSuppressIf :
1320 << ResetFlags (); >>
1321 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
1323 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1325 << WriteFlags (); >> // write the flags field
1326 vfrBooleanExpression
1328 { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+
1329 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1333 // This is the form for a grayoutif nested in a suppressif statement
1335 suppressIfGrayOutIf :
1336 << ResetFlags (); >>
1337 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>
1339 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1341 << WriteFlags (); >> // write the flags field
1342 vfrBooleanExpression
1346 //*****************************************************************************
1349 // grayoutif { flags = n, } <boolean_expression> endif;
1351 // You can have: grayoutif:suppressif:statements:endif
1352 // grayoutif:statements:endif
1355 vfrStatementGrayOutIf :
1356 << ResetFlags (); >>
1357 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
1359 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1361 << WriteFlags (); >> // write the flags field
1362 vfrBooleanExpression
1364 { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+
1365 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1369 // This is the format for a suppressif nested in a grayoutif
1371 grayoutIfSuppressIf :
1372 << ResetFlags (); >>
1373 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>
1375 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1377 << WriteFlags (); >> // write the flags field
1378 vfrBooleanExpression
1383 // These are the VFR statements that are valid inside a suppressif or grayoutif statement.
1385 suppressIfAndGrayoutIfSubstatements :
1387 vfrStatementTextText |
1388 vfrStatementCheckBox |
1389 vfrStatementNumeric |
1392 vfrStatementPassword |
1393 vfrStatementString |
1394 vfrStatementHidden |
1397 vfrStatementInventory |
1398 vfrStatementOrderedList |
1399 vfrStatementSaveRestoreDefaults
1402 //*****************************************************************************
1406 // password varid = MyNvData.Password,
1407 // prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
1408 // help = STRING_TOKEN(STR_PASSWORD_HELP),
1414 vfrStatementPassword :
1415 << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
1416 IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>
1417 VarId "=" vfrStructFieldNameArray[0] ","
1418 Prompt "=" getStringId ","
1419 KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
1421 FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
1424 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1426 << WriteFlagsKey (KeyValue, LineNum); >>
1427 MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
1428 MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
1429 Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>
1433 //*****************************************************************************
1437 // string varid = MyNv.String,
1438 // prompt = STRING_TOKEN(STR_STRING_PROMPT),
1439 // help = STRING_TOKEN(STR_STRING_HELP),
1440 // flags = INTERACTIVE,
1446 // Since flags and key are optional, we can't use Flags->getLine(). Therefore for error
1447 // reporting we save the line number of the "help" keyword.
1449 vfrStatementString :
1450 << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
1451 IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>
1452 VarId "=" vfrStructFieldNameArray[0] ","
1453 Prompt "=" getStringId ","
1454 KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
1457 flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1461 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1463 << WriteFlagsKey (KeyValue, LineNum); >>
1464 MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
1465 MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
1469 //*****************************************************************************
1472 // numeric varid = MyIfrNVData.HowOldAreYouInYears,
1473 // prompt = STRING_TOKEN(STR_NUMERIC_PROMPT),
1474 // help = STRING_TOKEN(STR_NUMERIC_HELP),
1475 // flags = INTERACTIVE, // flags is optional
1476 // key = 0x1234, // key is optional if (flags & INTERACTIVE = 0)
1479 // step = 1, // step is option, and step=1 if not specified
1480 // default = 0; // default is optional, and default=minimum if not specified
1483 // Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.
1484 // That check is done in WriteFlagsKey() function.
1486 vfrStatementNumeric :
1487 << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
1488 IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>
1489 VarId "=" vfrStructFieldName[2] ","
1490 Prompt "=" getStringId ","
1491 KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
1493 FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >>
1496 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1498 << WriteFlagsKey (KeyValue, LineNum); >>
1500 EndNumeric ";" << WriteMinMaxStepDefault (); >>
1504 // Parse minimum/maximum/step/default statements. Special cases:
1505 // - if step not specified, then the value is 1
1506 // - if default not specified, then the value is the min value specified
1507 // - if max < min, print a warning and swap the values (changes default too)
1510 << InitMinMaxStepDefault (); >>
1511 Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >>
1512 Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >>
1513 { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }
1514 { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> }
1518 //*****************************************************************************
1522 // date year varid = Date.Year, // "Date.Year" is a special case we recognize
1523 // prompt = STRING_TOKEN(STR_DATE_PROMPT),
1524 // help = STRING_TOKEN(STR_DATE_YEAR_HELP),
1530 // month varid = Date.Month,
1531 // prompt = STRING_TOKEN(STR_DATE_PROMPT),
1532 // help = STRING_TOKEN(STR_DATE_MONTH_HELP),
1538 // day varid = Date.Day,
1539 // prompt = STRING_TOKEN(STR_DATE_PROMPT),
1540 // help = STRING_TOKEN(STR_DATE_DAY_HELP),
1550 IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>
1551 vfrStructFieldName[2] ","
1552 dateTimeSubStatement
1553 IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>
1554 vfrStructFieldName[2] ","
1555 dateTimeSubStatement
1556 IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >>
1557 vfrStructFieldName[2] ","
1558 dateTimeSubStatement
1564 IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>
1565 vfrStructFieldName[2] ","
1566 dateTimeSubStatement
1567 IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>
1568 vfrStructFieldName[2] ","
1569 dateTimeSubStatement
1570 IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>
1571 vfrStructFieldName[2] ","
1572 dateTimeSubStatement
1576 //*****************************************************************************
1580 // text text = STRING_ID;
1581 // text text = STRING_ID, text = STRING_ID;
1582 // text text = STRING_ID, text = STRING_ID, flags = x, key = y;
1584 vfrStatementTextText :
1585 << ResetFlags (); >>
1586 IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>
1587 Help "=" getStringId ","
1589 getStringId // writes string identifier
1590 { "," Text "=" getStringId
1591 "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >>
1593 Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>
1598 //*****************************************************************************
1602 // inventory help = ID, text = ID;
1603 // inventory help = ID, text = id, text = ID;
1605 vfrStatementInventory :
1606 IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>
1607 Help "=" getStringId ","
1608 Text "=" getStringId // writes string identifier
1609 { "," Text "=" getStringId
1614 //*****************************************************************************
1618 // restore defaults,
1620 // prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
1621 // help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
1627 // prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
1628 // help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
1632 vfrStatementSaveRestoreDefaults :
1633 << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
1634 ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>
1635 | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>
1638 FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2));
1639 AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());
1641 Prompt "=" getStringId ","
1642 KH:Help "=" getStringId << LineNum = KH->getLine(); >>
1644 "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1647 "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1649 << WriteFlagsKey (KeyValue, LineNum); >>
1653 //*****************************************************************************
1657 // flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
1661 VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
1662 | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
1663 | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
1664 | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >>
1665 | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
1666 | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
1667 | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
1670 dateTimeSubStatement :
1671 Prompt "=" getStringId ","
1672 Help "=" getStringId ","
1673 << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
1674 minMaxStepDefault << WriteMinMaxStepDefault (); >>
1677 vfrStatementCheckBox :
1678 << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
1679 IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>
1680 VarId "=" vfrStructFieldName[1] ","
1681 Prompt "=" getStringId ","
1682 Help "=" getStringId ","
1683 FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
1685 Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>
1687 << WriteFlagsKey (KeyValue, LineNum); >>
1691 vfrStatementSubTitle :
1692 IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>
1693 getStringId // writes string indentifier
1697 //*****************************************************************************
1701 // title = STRING_TOKEN(STR_BANNER_TITLE),
1703 // align center; // or left or right
1706 // title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;
1708 vfrStatementBanner :
1709 IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>
1710 Title "=" getStringId ","
1712 Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>
1714 ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>
1715 | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>
1716 | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>
1719 Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>
1720 << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>
1724 //*****************************************************************************
1727 // oneof varid = MyNv.OneOfData,
1728 // prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
1729 // help = STRING_TOKEN(STR_ONE_OF_HELP),
1730 // option text = STRING_TOKEN(STR_ONE_OF_TEXT),
1732 // flags = DEFAULT | INTERACTIVE;
1734 // supressif/grayoutif are supported inside oneof stmt.
1735 // We do not restrict the number of oneOfOptionText to >=2, but >=1.
1736 // The situation that all oneOfOptionText are suppressed is also possiable.
1739 << ResetFlags (); >>
1740 IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>
1741 VarId "=" vfrStructFieldName[2] ","
1742 Prompt "=" getStringId "," // writes string identifier
1743 Help "=" getStringId "," // writes string identifier
1744 ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2.
1745 IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>
1748 //*****************************************************************************
1752 // orderedlist varid = MyNv.OrderedListData,
1753 // prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),
1754 // help = STRING_TOKEN(STR_ORDERED_LIST_HELP),
1755 // option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;
1756 // -- additional option text --
1759 vfrStatementOrderedList :
1760 << ResetFlags (); InitOrderedList(); >>
1761 IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>
1762 VarId "=" vfrStructFieldNameArray[1] ","
1763 Prompt "=" getStringId "," // writes string identifier
1764 Help "=" getStringId "," // writes string identifier
1765 orderedListOptionText ( orderedListOptionText )+
1766 IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>
1769 //*****************************************************************************
1773 // option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
1775 // Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to
1776 // be set, and value cannot be 0.
1778 orderedListOptionText :
1779 << UINT32 KeyValue = 0; >>
1780 IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
1781 Text "=" getStringId "," // writes string identifier
1782 Value "=" WVAL:Number "," <<
1783 if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {
1784 PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL);
1786 WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2));
1789 FF:Flags "=" orderedListFlagsField
1790 ("\|" orderedListFlagsField )*
1792 "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
1794 << WriteFlagsKey (KeyValue, FF->getLine()); >>
1795 ";" << mOptionCount++; >>
1798 //*****************************************************************************
1802 // flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
1804 // The ordered list flags field cannot have a default.
1806 orderedListFlagsField :
1807 VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
1808 | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
1809 | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
1810 | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
1811 | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
1812 | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
1813 | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>
1817 // Parse references to VFR structure field names of form "MyNvStructure.Field".
1818 // This implementation is specific to strings, passwords, and references in an
1819 // ordered list statement because we want to specify the size of the entire
1820 // field, rather than just one element. Then call a function to write out its
1821 // offset and length.
1823 vfrStructFieldNameArray[int FieldWidth] :
1824 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1825 SName:StringIdentifier
1827 SFieldName:StringIdentifier
1828 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1830 WriteFieldOffset (1,
1833 SFieldName->getText(),
1834 SFieldName->getLine(),
1844 // Parse references to VFR structure field names of form "MyNvStructure.Field",
1845 // then call a function to write out its offset and length.
1847 vfrStructFieldName[int FieldWidth] :
1848 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1849 SName:StringIdentifier
1851 SFieldName:StringIdentifier
1852 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1854 WriteFieldOffset (1,
1857 SFieldName->getText(),
1858 SFieldName->getLine(),
1867 //*****************************************************************************
1871 // MyNvStructure.FieldName[4]
1873 // Parse references to VFR structure field names of form "MyNvStructure.Field",
1874 // then call a function to write out the offset with no length.
1876 vfrStructFieldNameNL[int FieldWidth] :
1877 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1878 SName:StringIdentifier
1880 SFieldName:StringIdentifier
1881 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1883 WriteFieldOffset (0,
1886 SFieldName->getText(),
1887 SFieldName->getLine(),
1896 //*****************************************************************************
1899 // suppressif TRUE OR FALSE;
1900 // grayoutif FALSE OR TRUE;
1901 // option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
1902 // option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;
1906 suppressIfOptionText |
1907 grayOutIfOptionText |
1911 suppressIfOptionText :
1912 << ResetFlags (); >>
1913 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
1915 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1917 << WriteFlags (); >> // write the flags field
1918 vfrBooleanExpression
1920 { suppressIfGrayOutIf } ( commonOptionText )+
1921 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1924 grayOutIfOptionText :
1925 << ResetFlags (); >>
1926 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
1928 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1930 << WriteFlags (); >> // write the flags field
1931 vfrBooleanExpression
1933 { grayoutIfSuppressIf } ( commonOptionText )+
1934 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1938 << UINT32 KeyValue = 0; >>
1939 IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
1940 Text "=" getStringId "," // writes string identifier
1941 Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>
1942 FF:Flags "=" flagsField ("\|" flagsField )*
1944 "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
1946 << WriteFlagsKey (KeyValue, FF->getLine()); >>
1947 ";" << mOptionCount++; >>
1951 // Gets a string identifier. It must be a numeric value of form:
1953 // STRING_TOKEN(100)
1956 << unsigned short StrId; >>
1957 StringToken OpenParen
1958 IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >>
1962 //******************************************************************************
1964 // Parser class definition.
1966 class EfiVfrParser {
1969 // Parser definitions go here
1972 STRUCT_DEFINITION *mFirstStructDefinition;
1973 STRUCT_DEFINITION *mLastStructDefinition;
1974 INT32 mNvDataStructSize;
1975 INT32 mNonNvDataStructSize;
1977 // Flag to indicate that we're processing a ideqid VFR statement so that
1978 // we can do late checks on the statement.
1981 INT32 mLastNVVariableDataSize;
1982 GOTO_REFERENCE *mGotoReferences;
1983 FORM_ID_VALUE *mFormIdValues;
1984 VfrOpcodeHandler mOpcodeHandler;
1985 UINT16_LIST *mUint16List;
1986 UINT16_LIST *mLastUint16;
1987 UINT16_LIST *mDefinedLabels;
1988 UINT16_LIST *mDefinedVarStoreId;
1989 UINT16_LIST *mLastDefinedVarStoreId;
1990 UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;
1992 UINT32 mSubStmtFlags;
1993 UINT32 mSubStmtFlagsLineNum;
1994 EFI_GUID mFormSetGuid;
1995 UINT8 mNvDataStructDefined;
1996 UINT16 mClass, mSubclass;
1998 UINT32 mOptionCount; // how many "option" fields in a given statement
1999 UINT32 mLastVarIdSize;
2004 EfiVfrParser::SetIfStart (
2009 Routine Description:
2010 Invoked during VFR parsing when an "if" is encountered. Save the
2011 source line number so we can point to it if we don't find a
2012 corresponding endif later.
2015 LineNum - source line number where the "if" was parsed.
2025 EfiVfrParser::SetClass (
2031 Routine Description:
2032 Invoked during VFR parsing when a "class" statement is found. Check the
2033 range on the class value and save it for later.
2036 LineNum - source line number where the class statement was parsed.
2037 Value - the class value
2044 if (Value & 0xFFFF0000) {
2045 PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
2047 mClass |= (UINT16)Value;
2050 EfiVfrParser::SetSubclass (
2056 Routine Description:
2057 Invoked during VFR parsing when a subclass statement is found. Check the
2058 range on the value and save it for later.
2061 LineNum - source line number where the class statement was parsed.
2062 Value - the subclass value from the VFR statement
2069 if (Value & 0xFFFF0000) {
2070 PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
2072 mSubclass |= (UINT16)Value;
2074 VOID EfiVfrParser::WriteClass ()
2079 VOID EfiVfrParser::WriteSubclass ()
2081 WriteWord (mSubclass);
2084 VOID EfiVfrParser::WriteIfrBytes ()
2086 mOpcodeHandler.WriteIfrBytes ();
2089 EfiVfrParser::WriteFlagsKey (
2095 Routine Description:
2096 Write out the flags and key values from the previous VFR statement.
2097 Many statements take a flags/key pair. If not specified, then 0
2098 values are written out. However do not allow an interactive flags field
2099 to be specified if no key value is specified. Also, if NV_ACCESS flag
2100 is set but INTERACTIVE is not, then set interactive and issue a warning.
2103 KeyValue - the key value from the VFR statement
2104 LineNum - source line number where the statement was parsed
2111 if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {
2112 PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");
2114 if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {
2115 PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");
2116 mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;
2119 WriteWord (KeyValue);
2122 EfiVfrParser::InitOrderedList ()
2127 EfiVfrParser::EndOrderedList (
2131 if (mLastVarIdSize < mOptionCount) {
2132 PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
2136 EfiVfrParser::ResetFlags ()
2139 Routine Description:
2141 Flags are set for each substatement in a given one-of statement.
2142 To make sure there are no conflicts, for example setting DEFAULT on
2143 more than one substatement, we keep track of the flags at a statement
2144 level and a substatement level. This function resets the flags so
2145 we get a fresh start.
2156 mSubStmtFlagsLineNum = 0;
2160 // Test validity of flags value for a one-of statement.
2163 EfiVfrParser::TestOneOfFlags (
2168 // One of the fields must have had the default bit set
2170 if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {
2171 PrintWarningMessage (LineNum, "default value must be specified", NULL);
2175 EfiVfrParser::SetFlags (
2181 // Check for redefinitions and invalid combinations
2183 if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {
2184 PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");
2186 if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {
2187 PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");
2189 mSubStmtFlags |= Flags;
2190 mSubStmtFlagsLineNum = LineNum;
2193 EfiVfrParser::WriteFlags ()
2196 // Check value for validity
2198 if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT |
2199 EFI_IFR_FLAG_MANUFACTURING |
2200 EFI_IFR_FLAG_INTERACTIVE |
2201 EFI_IFR_FLAG_NV_ACCESS |
2202 EFI_IFR_FLAG_RESET_REQUIRED |
2203 EFI_IFR_FLAG_LATE_CHECK )) {
2204 PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);
2206 WriteByte ((UINT8)mSubStmtFlags, 'F');
2208 // We can now clear the substatement flags
2210 mStmtFlags |= mSubStmtFlags;
2214 // When we parse a min/max/step/default sequence, save off the values for
2215 // later use. Call this first to init the values.
2218 EfiVfrParser::InitMinMaxStepDefault ()
2226 EfiVfrParser::WriteMinMaxStepDefault ()
2228 WriteWord (mMinimumValue);
2229 WriteWord (mMaximumValue);
2230 WriteWord (mStepValue);
2231 WriteWord (mDefaultValue);
2234 EfiVfrParser::SetMinMaxStepDefault (
2245 mMinimumValue = Value;
2246 mDefaultValue = Value;
2250 } else if (MMSD == 1) {
2251 mMaximumValue = Value;
2253 // If min > max, then swap the values. That includes resetting the default
2256 if (mMinimumValue > mMaximumValue) {
2257 PrintWarningMessage (LineNum, NULL, "maximum < minimum");
2259 mMaximumValue = mMinimumValue;
2260 mMinimumValue = TempValue;
2261 mDefaultValue = mMinimumValue;
2266 } else if (MMSD == 2) {
2269 // Default specified. Make sure min <= default <= max.
2271 } else if (MMSD == 3) {
2272 mDefaultValue = Value;
2273 if (mMinimumValue > Value) {
2274 PrintErrorMessage (LineNum, NULL, "default value < minimum value");
2275 } else if (Value > mMaximumValue) {
2276 PrintErrorMessage (LineNum, NULL, "default value > maximum value");
2279 PrintErrorMessage (LineNum, "application error", "internal MMSD error");
2283 EfiVfrParser::AddLabel (
2291 // Added a label from the user VFR script. Make sure they haven't already
2292 // defined the same label elsewhere
2294 for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {
2295 if (Label->Value == LabelNumber) {
2296 PrintErrorMessage (LineNum, NULL, "label already defined");
2297 PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");
2301 Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
2302 if (Label == NULL) {
2303 PrintErrorMessage (0, NULL, "memory allocation error");
2306 memset ((char *)Label, 0, sizeof (UINT16_LIST));
2307 Label->Value = LabelNumber;
2308 Label->LineNum = LineNum;
2309 Label->Next = mDefinedLabels;
2310 mDefinedLabels = Label;
2313 EfiVfrParser::QueueIdEqValList (
2319 U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
2321 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");
2323 memset ((char *)U16, 0, sizeof (UINT16_LIST));
2325 if (mUint16List == NULL) {
2328 mLastUint16->Next = U16;
2334 EfiVfrParser::FlushQueueIdEqValList ()
2339 // We queued up a list of IdEqValList items. The IFR requires a count
2340 // followed by the actual values. Do it.
2343 mLastUint16 = mUint16List;
2344 while (mLastUint16 != NULL) {
2346 mLastUint16 = mLastUint16->Next;
2348 // BUGBUG -- check for more than 16K items?
2351 // Now write the values.
2353 mLastUint16 = mUint16List;
2354 while (mLastUint16 != NULL) {
2355 WriteWord ((UINT32)mLastUint16->Value);
2356 mLastUint16 = mLastUint16->Next;
2361 mLastUint16 = mUint16List;
2362 while (mUint16List != NULL) {
2363 mLastUint16 = mUint16List->Next;
2365 mUint16List = mLastUint16;
2369 EfiVfrParser::PrintErrorMessage (
2378 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2379 Error (FileName, LineNum, 0, Msg1, Msg2);
2381 Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);
2385 EfiVfrParser::PrintWarningMessage (
2394 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2395 Warning (FileName, LineNum, 0, Msg1, Msg2);
2397 Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);
2402 ANTLRAbstractToken *Tok,
2405 ANTLRTokenType ETok,
2410 Routine Description:
2411 Called by the parser base class as a result of parse syntax errors.
2414 Tok - token that caused the error
2416 Eset - index in token table of the expected token
2427 LineNum = Tok->getLine ();
2428 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2430 // Sometimes the token number is 0, in which case I don't know what to
2434 Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");
2437 // If we were expecting an endif, then report the line where the corresponding
2440 if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {
2442 FileName = ConvertLineNumber (&LineNum);
2443 Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);
2445 Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);
2451 EfiVfrParser::init()
2454 Routine Description:
2455 Initializations function for our parser.
2465 ANTLRParser::init();
2468 // Used for queuing a variable list of UINT16's
2472 mFirstStructDefinition = NULL;
2473 mLastStructDefinition = NULL;
2474 mNvDataStructSize = 0;
2475 mNonNvDataStructSize = 0;
2476 mNvDataStructDefined = 0;
2477 mGotoReferences = NULL;
2478 mFormIdValues = NULL;
2479 mDefinedLabels = NULL;
2483 mDefinedVarStoreId = NULL;
2484 mLastDefinedVarStoreId = NULL;
2486 mLastNVVariableDataSize = 0;
2488 memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));
2491 // Destructor for the parser.
2493 EfiVfrParser::~EfiVfrParser(VOID)
2498 EfiVfrParser::Cleanup (VOID)
2501 Routine Description:
2502 Free memory allocated during parsing
2512 STRUCT_DEFINITION *NextStruct;
2513 STRUCT_FIELD_DEFINITION *NextField;
2515 UINT16_LIST *NextU16List;
2518 // Free up the structure definitions if any
2520 while (mFirstStructDefinition != NULL) {
2522 // Free up all the fields for this struct
2524 while (mFirstStructDefinition->Field != NULL) {
2525 NextField = mFirstStructDefinition->Field->Next;
2526 free (mFirstStructDefinition->Field->Name);
2527 free (mFirstStructDefinition->Field);
2528 mFirstStructDefinition->Field = NextField;
2530 NextStruct = mFirstStructDefinition->Next;
2531 free (mFirstStructDefinition->Name);
2532 free (mFirstStructDefinition);
2533 mFirstStructDefinition = NextStruct;
2536 // Free up the goto references and form id defines
2538 FreeGotoReferences ();
2540 // Free up label list
2542 while (mDefinedLabels != NULL) {
2543 NextU16List = mDefinedLabels->Next;
2544 delete (mDefinedLabels);
2545 mDefinedLabels = NextU16List;
2548 // Free up the list of defined variable storage IDs
2550 while (mDefinedVarStoreId != NULL) {
2551 NextU16List = mDefinedVarStoreId->Next;
2552 delete (mDefinedVarStoreId);
2553 mDefinedVarStoreId = NextU16List;
2558 EfiVfrParser::AtoX (
2565 Routine Description:
2566 Given a pointer to a ascii hex string, convert to a number with the given
2570 HexString - pointer to a string of format 30BCA
2571 Size - number of bytes to convert
2572 HexValue - return result
2575 The number of bytes converted.
2584 while (Count < NumBytes) {
2585 if ((*HexString >= '0') && (*HexString <= '9')) {
2586 Value = *HexString - '0';
2587 } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
2588 Value = *HexString - 'a' + 10;
2589 } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
2590 Value = *HexString - 'A' + 10;
2595 *HexValue = (*HexValue << 4) | Value;
2596 if ((*HexString >= '0') && (*HexString <= '9')) {
2597 Value = *HexString - '0';
2598 } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
2599 Value = *HexString - 'a' + 10;
2600 } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
2601 Value = *HexString - 'A' + 10;
2605 *HexValue = (*HexValue << 4) | Value;
2612 EfiVfrParser::WriteGuidValue (
2613 UINT32 TokenLineNum,
2628 Routine Description:
2629 A Guid was parsed, likely of format:
2630 #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }
2632 Write out the value.
2635 TokenLineNum - line number where the guid was used
2636 G1-G11 - the 11 fields of the guid value
2647 mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);
2648 mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);
2649 mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);
2650 mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);
2651 mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);
2652 mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);
2653 mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);
2654 mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);
2655 mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);
2656 mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);
2657 mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);
2659 WriteDWord (mFormSetGuid.Data1, 'G');
2660 WriteWord (mFormSetGuid.Data2);
2661 WriteWord (mFormSetGuid.Data3);
2662 WriteByte (mFormSetGuid.Data4[0], 0);
2663 WriteByte (mFormSetGuid.Data4[1], 0);
2664 WriteByte (mFormSetGuid.Data4[2], 0);
2665 WriteByte (mFormSetGuid.Data4[3], 0);
2666 WriteByte (mFormSetGuid.Data4[4], 0);
2667 WriteByte (mFormSetGuid.Data4[5], 0);
2668 WriteByte (mFormSetGuid.Data4[6], 0);
2669 WriteByte (mFormSetGuid.Data4[7], 0);
2672 EfiVfrParser::WriteFieldOffset (
2685 Routine Description:
2686 A VFR script referenced the NV store structure. Given the structure's name
2687 and the field's name, write the offset of the field to the output file.
2690 WriteLength - write the field length byte out
2691 StructName - name of the NV store structure
2692 LineNum1 - line number in the VFR where we are (for error printing)
2693 FieldName - the name of the field within the NV store structure
2694 LineNum2 - line number in the VFR where FieldName is referenced
2695 ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex]
2696 IsArrayIndex - non-zero if an array index was specified
2697 FieldWidth - expected size for the Field (1 byte? 2 bytes?)
2698 WriteArraySize - write the size of the entire field, not the size of a single element
2705 STRUCT_DEFINITION *StructDef;
2706 STRUCT_FIELD_DEFINITION *FieldDef;
2711 // If we're writing an array size, then they better have referenced the field without an
2714 if (WriteArraySize && IsArrayIndex) {
2715 sprintf (Msg, "array index specified where an array is required");
2716 PrintErrorMessage (LineNum2, FieldName, Msg);
2721 // The reference index starts at 1 not 0
2723 if (IsArrayIndex && (ArrayIndex < 1)) {
2724 printf ("WARNING: array index shouldn't be less than 1");
2727 // Look through our list of known structures for a match
2729 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
2731 // Check for matching structure name
2733 if (strcmp (StructDef->Name, StructName) == 0) {
2735 // Mark it as referenced (for debug purposes only). Check the
2736 // flag that indicates that we have already found a varstore VFR
2737 // statement for it.
2739 StructDef->Referenced++;
2740 if (StructDef->VarStoreIdValid == 0) {
2742 // Set it valid so we don't flag it multiple times, then emit the error
2744 StructDef->VarStoreIdValid = 1;
2745 PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");
2748 // Let the opcode-handler know which variable storage we're now using
2751 mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);
2753 mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);
2756 // Found matching structure name. Now find the matching field name
2758 for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
2759 if (strcmp (FieldDef->Name, FieldName) == 0) {
2761 // Make sure the variable size is valid
2763 if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {
2764 sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');
2765 PrintErrorMessage (LineNum2, FieldName, Msg);
2768 // If they specified an index (MyVfrData.FieldX[10]), then make sure that the
2769 // data structure was declared as an array, and that the index is in bounds.
2770 // If they did not specify an index, then we'll assume 0. This is required for
2774 VarSize = FieldDef->DataSize;
2775 if (FieldDef->IsArray == 0) {
2776 PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");
2779 if (FieldDef->ArrayLength < ArrayIndex) {
2780 PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");
2784 if (FieldDef->IsArray) {
2785 VarSize = FieldDef->DataSize * FieldDef->ArrayLength;
2787 VarSize = FieldDef->DataSize;
2791 // If we're in the middle of a ideqid VFR statement, then this is the second
2792 // variable ID that we're now processing. Make sure that its size is the same
2793 // as the first variable.
2796 if (mLastVarIdSize != VarSize) {
2797 PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");
2801 mLastVarIdSize = VarSize;
2803 // If we're supposed to write an array size, then require it to be an array
2805 if (WriteArraySize && !FieldDef->IsArray) {
2806 PrintErrorMessage (LineNum2, FieldName, "array required");
2810 // Write the variable offset and size. If we're in the non-NV structure, then
2811 // set the offset beyond the NV data structure size.
2813 Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);
2814 if (StructDef->IsNonNV) Offset += mNvDataStructSize;
2817 if (WriteArraySize) {
2818 if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {
2819 PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");
2822 WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);
2824 WriteByte (FieldDef->DataSize, 0);
2830 sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);
2831 PrintErrorMessage (LineNum2, Msg, NULL);
2832 PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);
2837 // The structure was not found in the defined list. See if it's the "Date" structure
2839 if (strcmp (StructName, "Date") == 0) {
2841 // BUGBUG -- remove support for Date and Time as valid structure
2842 // names. They should use the NON_NV_DATA_MAP structure for this.
2844 // Someone specified Date.Years|Months|Days
2845 // BUGBUG -- define some constants for the IDs used here
2846 // Length == 0 implies that this is not user NV data storage.
2848 if (strcmp (FieldName, "Year") == 0) {
2850 // Write ID (offset), ID, and size
2852 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);
2856 } else if (strcmp (FieldName, "Month") == 0) {
2858 // Write ID (offset), ID, and size
2860 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);
2864 } else if (strcmp (FieldName, "Day") == 0) {
2866 // Write ID (offset), ID, and size
2868 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);
2873 PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");
2876 } else if (strcmp (StructName, "Time") == 0) {
2878 // Someone specified Time.Hours|Minutes|Seconds
2879 // BUGBUG -- define some constants for the IDs used here
2881 if (strcmp (FieldName, "Hours") == 0) {
2883 // Write ID (offset), ID, and size
2885 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);
2889 } else if (strcmp (FieldName, "Minutes") == 0) {
2891 // Write ID (offset), ID, and size
2893 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);
2897 } else if (strcmp (FieldName, "Seconds") == 0) {
2899 // Write ID (offset), ID, and size
2901 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);
2906 PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");
2910 PrintErrorMessage (LineNum1, StructName, "undefined structure");
2915 EfiVfrParser::StartStructDefinition (
2921 Routine Description:
2922 Called when we encounter a new "struct _MY_STRUCT..." statement while parsing.
2923 Initialize internal data and structures for parsing the fields of the structure.
2926 LineNum - line number in the source file (for error reporting purposes)
2927 IsNonNv - flag indicating (if nonzero) that the variable referred to is not in
2928 the standard NV store.
2934 STRUCT_DEFINITION *StructDef;
2936 // Allocate memory for the structure record
2938 StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));
2939 memset (StructDef, 0, sizeof (STRUCT_DEFINITION));
2940 StructDef->LineNum = LineNum;
2942 // Set flag indicating non-NV data structure or not
2944 StructDef->IsNonNV = IsNonNV;
2946 // Add it to the end of our linked list. If it's the first one
2947 // defined, then it's the default varstore ID, so set it valid.
2949 if (mFirstStructDefinition == NULL) {
2950 mFirstStructDefinition = StructDef;
2951 StructDef->VarStoreIdValid = 1;
2953 mLastStructDefinition->Next = StructDef;
2955 mLastStructDefinition = StructDef;
2958 EfiVfrParser::EndStructDefinition (
2963 STRUCT_DEFINITION *StructDef;
2964 STRUCT_FIELD_DEFINITION *FieldDef;
2967 // Make sure they have not already defined a structure with this name
2969 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
2970 if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {
2971 PrintErrorMessage (LineNum, StructName, "structure with this name already defined");
2973 // Fall through and fill in the rest of the structure information. We do
2974 // this because the structure has already been added to our global list,
2975 // so will be used elsewhere, so we want it to contain valid fields.
2980 // Allocate memory for the structure name
2982 mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);
2983 strcpy (mLastStructDefinition->Name, StructName);
2985 // Compute the structure size, and the offsets to each field
2988 for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
2989 FieldDef->Offset = Offset;
2990 Offset += FieldDef->ArrayLength * FieldDef->DataSize;
2992 mLastStructDefinition->Size = Offset;
2994 // Go through all the structure we have so far and figure out (if we can)
2995 // the size of the non-NV storage. We also assume that the first structure
2996 // definition is the primary/default storage for the VFR form.
2998 if (mNonNvDataStructSize == 0) {
2999 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3000 if (StructDef->IsNonNV) {
3001 mNonNvDataStructSize = StructDef->Size;
3006 if (mNvDataStructSize == 0) {
3007 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3008 if (StructDef->IsNonNV == 0) {
3009 mNvDataStructSize = StructDef->Size;
3016 EfiVfrParser::AddStructField (
3025 Routine Description:
3026 We're parsing the VFR structure definition. Add another defined field to
3030 FieldName - name of the field in the structure.
3031 LineNum - the line number from the input (preprocessor output) file
3032 DataSize - the size of the field (1, 2, or 4 bytes)
3033 ArrayLength - the number of elements (for array)
3034 IsArray - non-zero if the field is an array
3041 STRUCT_FIELD_DEFINITION *FieldDef;
3042 STRUCT_FIELD_DEFINITION *Temp;
3044 // Make sure we don't already have a field of this name in our structure
3046 for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
3047 if (strcmp (FieldDef->Name, FieldName) == 0) {
3048 PrintErrorMessage (LineNum, FieldName, "field with this name already defined");
3053 // If it's an array, then they better not have a size of 0. For example:
3054 // UINT8 MyBytes[0];
3056 if (IsArray && (ArrayLength <= 0)) {
3057 PrintErrorMessage (LineNum, FieldName, "invalid array size");
3061 // Allocate memory for a new structure field definition
3063 FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));
3064 memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));
3065 FieldDef->ArrayLength = ArrayLength;
3066 FieldDef->DataSize = DataSize;
3067 FieldDef->IsArray = IsArray;
3068 FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);
3069 strcpy (FieldDef->Name, FieldName);
3071 // Add it to the end of the field list for the currently active structure
3073 if (mLastStructDefinition->Field == NULL) {
3074 mLastStructDefinition->Field = FieldDef;
3076 mLastStructDefinition->LastField->Next = FieldDef;
3078 mLastStructDefinition->LastField = FieldDef;
3081 EfiVfrParser::AddVarStore (
3082 INT8 *StructName, // actual name of the structure
3083 INT8 *VarName, // actual NV variable name
3084 UINT16 VarStoreId, // key value
3085 INT32 LineNum // parse line number (for error reporting)
3089 Routine Description:
3090 Called while parsing a varstore statement. Add the variable store
3094 StructName - the name of the typedef'ed structure to use
3095 VarName - the NV variable name as specified in the varstore statement
3096 VarStoreId - the variable store ID as specified in the varstore statememt
3097 LineNum - the line number from the input (preprocessor output) file
3104 STRUCT_DEFINITION *StructDef;
3105 UINT16_LIST *L16Ptr;
3107 // Go through our list of previously-defined variable store IDs and
3108 // make sure this one is not a duplicate in name or key value.
3110 for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {
3111 if (L16Ptr->Value == VarStoreId) {
3112 PrintErrorMessage (LineNum, "variable storage key already used", NULL);
3113 PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);
3117 // Key value of 0 is invalid since that's assigned by default to the default
3118 // variable store (the first structure parsed).
3120 if (VarStoreId == 0) {
3121 PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);
3124 // Create a new element to add to the list
3126 L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));
3127 memset (L16Ptr, 0, sizeof (UINT16_LIST));
3128 L16Ptr->LineNum = LineNum;
3129 L16Ptr->Value = VarStoreId;
3130 if (mDefinedVarStoreId == NULL) {
3131 mDefinedVarStoreId = L16Ptr;
3133 mLastDefinedVarStoreId->Next = L16Ptr;
3135 mLastDefinedVarStoreId = L16Ptr;
3137 // Find the structure definition with this name
3139 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3140 if (strcmp (StructDef->Name, StructName) == 0) {
3142 // Make sure they did not already define a variable storage ID
3143 // for this structure.
3145 if (StructDef->VarStoreId != 0) {
3146 PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");
3147 PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");
3149 StructDef->VarStoreId = VarStoreId;
3150 StructDef->VarStoreIdValid = 1;
3151 StructDef->VarStoreLineNum = LineNum;
3152 WriteWord (StructDef->Size);
3154 WriteByte(*VarName, 0);
3161 PrintErrorMessage (LineNum, StructName, "structure with this name not defined");
3164 EfiVfrParser::WriteDWord (
3170 Routine Description:
3171 During parsing, we came upon some code that requires a 32-bit value be
3172 written to the VFR binary file. Queue up the 4 bytes.
3175 Value - the 32-bit value to write
3176 KeyByte - a single character which gets written out beside the first byte.
3177 This is used to tag the data in the output file so that during
3178 debug you have an idea what the value is.
3186 // Write 4 bytes, little endian. Specify a key byte only on the first one
3188 mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);
3190 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3192 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3194 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3197 EfiVfrParser::WriteOpByte (
3203 Routine Description:
3205 During parsing, we came upon a new VFR opcode. At this point we flush
3206 the output queue and then queue up this byte (with 'O' for opcode tag).
3210 ByteValue - opcode value
3218 mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
3221 EfiVfrParser::WriteByte (
3227 Routine Description:
3229 During parsing of the VFR we spoonfeed this function with bytes to write to
3230 the output VFR binary file. This function simply queues up the bytes, and
3231 the queue gets flushed each time a new VFR opcode is encountered.
3235 ByteValue - raw byte to write
3236 Key - character to tag the byte with when we write ByteValue to the
3245 mOpcodeHandler.AddByte (ByteValue, Key);
3248 EfiVfrParser::WriteWord (
3253 Routine Description:
3254 During VFR parsing we came upon a case where we need to write out a
3255 16-bit value. Queue it up.
3258 Value - value to write.
3265 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3266 mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
3269 EfiVfrParser::WriteStringIdWord (
3273 mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
3274 mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
3277 EfiVfrParser::FreeGotoReferences ()
3280 Routine Description:
3281 Called during cleanup to free up the memory we allocated when
3282 keeping track of VFR goto statements.
3292 GOTO_REFERENCE *CurrRef;
3293 GOTO_REFERENCE *NextRef;
3294 FORM_ID_VALUE *CurrFormId;
3295 FORM_ID_VALUE *NextFormId;
3300 // Go through all the "goto" references and make sure there was a
3301 // form ID of that value defined.
3303 for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {
3305 for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {
3306 if (CurrRef->Value == CurrFormId->Value) {
3312 sprintf (Name, "%d", (UINT32)CurrRef->Value);
3313 PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");
3317 // Now free up the form id and goto references
3319 CurrFormId = mFormIdValues;
3320 while (CurrFormId != NULL) {
3321 NextFormId = CurrFormId->Next;
3323 CurrFormId = NextFormId;
3325 mFormIdValues = NULL;
3326 CurrRef = mGotoReferences;
3327 while (CurrRef != NULL) {
3328 NextRef = CurrRef->Next;
3332 mGotoReferences = NULL;
3335 EfiVfrParser::AddGotoReference (
3341 Routine Description:
3342 During VFR parsing we came upon a goto statement. Since we support
3343 forward references, save the referenced label and at the end of parsing
3344 we'll check that the label was actually defined somewhere.
3347 GotoNumber - the label number referenced
3348 LineNum - the line number where the reference was made (used for
3356 GOTO_REFERENCE *NewRef;
3358 NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));
3359 if (NewRef == NULL) {
3360 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
3363 memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));
3364 NewRef->Value = (UINT16)GotoNumber;
3365 NewRef->RefLineNum = LineNum;
3366 NewRef->Next = mGotoReferences;
3367 mGotoReferences = NewRef;
3370 EfiVfrParser::AddFormId (
3376 Routine Description:
3377 This function is called when we parse "form formid = 3" statements.
3378 We save the form ID valud so we can verify that duplicates are not
3379 defined. Also, these are the targets of goto statements, so when we're
3380 done parsing the script we also go through all the goto statements to
3381 check that there was a target FormId defined as referenced by each
3384 Note that formid = 0 is invalid.
3387 FormIdValue - the parsed value for the Form ID
3388 LineNum - line number of the source file we're parsing
3395 FORM_ID_VALUE *NewFormId;
3400 // Verify that FormId != 0
3402 if (FormIdValue == 0) {
3403 FileName = ConvertLineNumber (&LineNum);
3404 Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);
3408 // First go through all previously defined form IDs and make sure they have not defined
3411 for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {
3412 if ((UINT16)FormIdValue == NewFormId->Value) {
3413 FileName = ConvertLineNumber (&LineNum);
3414 LineNum2 = NewFormId->LineNum;
3415 FileName2 = ConvertLineNumber (&LineNum2);
3416 Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);
3417 Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);
3422 // Allocate memory for a new one
3424 NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));
3425 if (NewFormId == NULL) {
3426 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
3429 memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));
3430 NewFormId->LineNum = LineNum;
3431 NewFormId->Next = mFormIdValues;
3432 NewFormId->Value = (UINT16)FormIdValue;
3433 mFormIdValues = NewFormId;
3436 EfiVfrParser::GetNumber (
3444 if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {
3445 AtoX (NumStr + 2, 4, &Value);
3447 Value = (UINT32)atoi (NumStr);
3452 if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {
3453 PrintErrorMessage (LineNum, NumStr, "value out of range");
3461 } // end grammar class