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
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 <UefiBaseTypes.h>
26 #include <CommonLib.h>
27 #include <MultiPhase.h>
28 #include "EfiUtilityMsgs.h"
30 #include "VfrServices.h"
37 #include <process.h> // for spawn functions
47 // Base info for DLG-generated scanner
49 #include "DLexerBase.h"
52 // Include the scanner file generated by DLG
56 class DLGLexerVfr : public DLGLexer
59 DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};
60 INT32 errstd (char *Text)
62 printf ("unrecognized input '%s'\n", Text);
67 // Base token definitions for ANTLR
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.
78 #define PREPROCESSOR_COMMAND "gcc "
79 #define PREPROCESSOR_OPTIONS "-x c -E -P -DVFRCOMPILE "
80 #define FILE_SEP_CHAR '/'
81 #define FILE_SEP_STRING "/"
83 #define PREPROCESSOR_COMMAND "cl.exe "
84 #define PREPROCESSOR_OPTIONS "/nologo /P /TC /DVFRCOMPILE "
85 #define FILE_SEP_CHAR '/'
86 #define FILE_SEP_STRING "/"
89 typedef ANTLRCommonToken ANTLRToken;
92 // Specify the filename extensions for the files we generate.
94 #define VFR_BINARY_FILENAME_EXTENSION ".c"
95 #define VFR_LIST_FILENAME_EXTENSION ".lst"
125 Application entry point function. Parse command-line arguments,
126 invoke the parser, clean up, and return.
129 argc - standard argc passed to main() per C conventions
130 argv - standard argv passed to main() per C conventions
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
146 // Set our program name for the error printing routines.
147 // Then set printing limits.
149 SetUtilityName (PROGRAM_NAME);
150 SetPrintLimits (20, 20, 30);
152 // Process the command-line arguments
154 if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {
161 // Verify the VFR script file exists
163 if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {
164 Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");
169 // Now close the file and make a system call to run the preprocessor
173 Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10;
174 if (gOptions.CPreprocessorOptions != NULL) {
175 Len += strlen (gOptions.CPreprocessorOptions) + 1;
177 if (gOptions.IncludePaths != NULL) {
178 Len += strlen (gOptions.IncludePaths) + 1;
180 Cmd = (char *)malloc (Len);
182 Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");
186 strcpy (Cmd, PREPROCESSOR_OPTIONS);
187 if (gOptions.IncludePaths != NULL) {
188 strcat (Cmd, gOptions.IncludePaths);
191 if (gOptions.CPreprocessorOptions != NULL) {
192 strcat (Cmd, gOptions.CPreprocessorOptions);
195 strcat (Cmd, gOptions.VfrFileName);
197 Status = _spawnlp (_P_WAIT, PREPROCESSOR_COMMAND, Cmd, NULL);
200 char CommandLine[1000];
204 // Lean the slashes forward.
206 for (p = gOptions.PreprocessorOutputFileName; *p; p++) {
213 // Lean the slashes forward.
215 for (p = Cmd; *p; p++) {
221 sprintf(CommandLine, "%s %s > %s", PREPROCESSOR_COMMAND, Cmd, gOptions.PreprocessorOutputFileName);
222 Status = system (CommandLine);
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);
233 // Open the preprocessor output file
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);
242 // Define input VFR file
244 DLGFileInput InputFile (VfrFptr);
246 // Define an instance of the scanner
248 DLGLexerVfr Scanner (&InputFile);
250 // Define token buffer between scanner and parser
252 ANTLRTokenBuffer Pipe (&Scanner);
254 // Create a token to use as a model
258 // Tell the scanner what type the token is
260 Scanner.setToken (&Tok);
262 // Create an instance of our parser
264 EfiVfrParser Parser (&Pipe);
266 // Initialize the parser
269 Status = GetUtilityStatus ();
270 if (Status != STATUS_SUCCESS) {
275 // Start the first rule
279 // Close the input script file
282 Parser.WriteIfrBytes ();
284 // Call cleanup, which does some extra checking of the script
289 // If we had an error somewhere, delete our output files so that
290 // a subsequent build will rebuild them.
292 Status = GetUtilityStatus ();
293 if (Status == STATUS_ERROR) {
294 remove (gOptions.IfrOutputFileName);
304 Free up memory allocated during parsing.
315 // Free up our string we allocated to track the include paths
317 if (gOptions.IncludePaths != NULL) {
318 free (gOptions.IncludePaths);
319 gOptions.IncludePaths = NULL;
322 // Free up our string we allocated to track preprocessor options
324 if (gOptions.CPreprocessorOptions != NULL) {
325 free (gOptions.CPreprocessorOptions);
326 gOptions.CPreprocessorOptions = NULL;
339 Process the command-line arguments.
342 Argc - standard argc passed to main()
343 Argv - standard argv passed to main()
346 STATUS_SUCCESS - program should continue (all args ok)
351 char *CPreprocessorOptions;
353 char CopyStr[MAX_PATH];
357 // Put options in known state.
359 memset ((char *)&gOptions, 0, sizeof (OPTIONS));
361 // Go through all the arguments that start with '-'
365 while ((Argc > 0) && (Argv[0][0] == '-')) {
367 // -? or -h help option -- return an error for printing usage
369 if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {
373 // -l to create a listing output file
375 } else if (stricmp (Argv[0], "-l") == 0) {
376 gOptions.CreateListFile = 1;
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.
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");
388 Len = strlen (" -I ");
389 Len += strlen (Argv[0]) + 2;
390 if (gOptions.IncludePaths != NULL) {
391 Len += strlen (gOptions.IncludePaths);
393 IncludePaths = (CHAR8 *)malloc (Len);
394 if (IncludePaths == NULL) {
395 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
399 if (gOptions.IncludePaths != NULL) {
400 strcpy (IncludePaths, gOptions.IncludePaths);
401 free (gOptions.IncludePaths);
403 strcat (IncludePaths, " -I ");
404 strcat (IncludePaths, Argv[0]);
405 gOptions.IncludePaths = IncludePaths;
407 // -od OutputDirectory to define a common directory for output files
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");
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) {
422 // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
423 // Turn them all into a single string.
425 } else if (stricmp (Argv[0], "-ppflag") == 0) {
427 Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
432 Len = strlen (Argv[0]) + 2;
433 if (gOptions.CPreprocessorOptions != NULL) {
434 Len += strlen (gOptions.CPreprocessorOptions);
436 CPreprocessorOptions = (CHAR8 *)malloc (Len);
437 if (CPreprocessorOptions == NULL) {
438 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
441 CPreprocessorOptions[0] = 0;
442 if (gOptions.CPreprocessorOptions != NULL) {
443 strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
444 free (gOptions.CPreprocessorOptions);
446 strcat (CPreprocessorOptions, " ");
447 strcat (CPreprocessorOptions, Argv[0]);
448 gOptions.CPreprocessorOptions = CPreprocessorOptions;
450 Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
457 // Must specify at least the vfr file name
460 Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
462 } else if (Argc < 1) {
463 Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");
466 strcpy (gOptions.VfrFileName, Argv[0]);
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.
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);
481 strcpy (gOptions.PreprocessorOutputFileName, Cptr+1);
482 strcpy (gOptions.VfrBaseFileName, Cptr+1);
484 for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++);
487 // Terminate the vfr file basename at the extension
489 for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
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
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.
507 if (gOptions.OutputDirectory[0] == 0) {
510 _getcwd (CopyStr, sizeof (CopyStr));
512 getcwd (CopyStr, sizeof (CopyStr));
514 strcpy (gOptions.OutputDirectory, CopyStr);
517 // Make sure output directory has a trailing backslash
519 if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\' ||
520 gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '/') {
521 strcat (gOptions.OutputDirectory, FILE_SEP_STRING);
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.
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);
533 // We set a default list file name, so if they do not
534 // want a list file, null out the name now.
536 if (gOptions.CreateListFile == 0) {
537 gOptions.VfrListFileName[0] = 0;
539 return STATUS_SUCCESS;
547 Print utility usage instructions
558 const char *Help[] = {
560 "VfrCompile version " VFR_COMPILER_VERSION,
562 " Usage: VfrCompile {options} [VfrFile]",
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",
575 for (Index = 0; Help[Index] != NULL; Index++) {
576 fprintf (stdout, "%s\n", Help[Index]);
588 PARSER_LINE_DEFINITION *gLineDefinition = NULL;
589 PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;
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
607 TokenString - the parsed string as shown above
608 TokenLine - the line number in the preprocessed output file
615 PARSER_LINE_DEFINITION *LineDef;
619 // Allocate a structure in which we can keep track of this line information.
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);
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.
630 for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
632 LineDef->FileName = (CHAR8 *)malloc (strlen (Cptr));
634 strcpy (LineDef->FileName, Cptr);
635 for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
638 // Now add this new one to the list
640 if (gLineDefinition == NULL) {
641 gLineDefinition = LineDef;
643 gLastLineDefinition->Next = LineDef;
645 gLastLineDefinition = LineDef;
647 Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
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.
664 LineNum - the line number in the preprocessor-output file.
667 Returns a pointer to the source file name. Also returns the line number
668 in the provided LineNum argument
672 PARSER_LINE_DEFINITION *LineDef;
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.
680 for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
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.
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;
694 // Last one in the list of line definitions, so has to be right
696 *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
697 return LineDef->FileName;
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.
711 #lexclass QUOTED_STRING
712 #token TheString "~[\"]*\"" << mode (START); >>
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.
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); >>
727 // Define a lexclass for skipping over C++ style comments
729 #lexclass CPP_COMMENT
730 #token "~[\n]*" << skip (); >>
731 #token "\n" << skip (); mode (START); newline (); >>
734 // Standard lexclass is START
739 // Find start of C++ style comments
741 #token "//" << skip (); mode (CPP_COMMENT); >>
746 #token "[\ \t]" << skip (); >>
749 // Skip over newlines, but count them
751 #token "\n" << skip (); newline (); >>
754 // Skip pragma pack statements
756 #token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
759 // Skip over 'extern' in any included .H file
761 #token "extern" << skip (); >>
764 // Tokens for the different keywords. Syntax is:
765 // TokenName("ErrorMessageText") "TokenString"
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
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"
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("<=") "<="
873 // Define the class and subclass tokens
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"
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"
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("]") "\]"
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
903 #token InvalidCharacters("invalid characters") "~[;:=,\.\|]"
906 // This is the overall definition of a VFR form definition script.
909 ( dataStructDefinition )*
911 ( vfrStatementVarStore )*
913 EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>
918 FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>
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 ()
940 Title "=" getStringId ","
941 Help "=" getStringId ","
943 // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)
945 << WriteDWord (0, 0); WriteDWord (0, 0); >>
946 Class "=" CVAL:classDefinition "," << WriteClass (); >>
947 Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >>
948 << WriteWord (mNvDataStructSize); >>
952 // A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C
955 validClassNames ( "\|" 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"); >>
970 // A form can only be of one subclass type.
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"); >>
981 // Parse a C type data structure for storing VFR setup data. Allow:
982 // typedef struct _XXX_ {
986 dataStructDefinition :
987 << int IsNonNV = 0; >>
991 NonNvDataMap << IsNonNV = 1; >>
994 ) << StartStructDefinition (IsNonNV, S->getLine()); >>
997 CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >>
1002 // Parse a C type data structure for defining data that is not stored in NV.
1003 // typedef struct _NON_NV_DATA_MAP {
1005 // } NON_NV_DATA_MAP;
1007 nonNvDataStructDefinition :
1010 { StringIdentifier }
1013 CloseBrace NAME:StringIdentifier << AddStructField (NAME->getText(), NAME->getLine(), 0, 0, 0); >>
1018 ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *
1021 //*****************************************************************************
1027 // Used while parsing the NV data map structures.
1030 << int ArrayLength = 1; char IsArray = 0; >>
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); >>
1037 //*****************************************************************************
1043 // Used while parsing the NV data map structures.
1046 << int ArrayLength = 1; char IsArray = 0; >>
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); >>
1053 //*****************************************************************************
1059 // Used while parsing the NV data map structures.
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); >>
1069 //*****************************************************************************
1075 // Used while parsing the NV data map structures.
1078 << int ArrayLength = 1; char IsArray = 0; >>
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); >>
1085 //*****************************************************************************
1089 // title = STRING_TOKEN(STR_FORM_TITLE);
1090 // -- form statements --
1093 // The Form ID cannot be 0
1096 FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >>
1098 VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>
1100 Title "=" getStringId ";" // writes string identifier
1102 ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>
1106 // VFR statements in a formset
1109 vfrStatementSubTitle |
1111 vfrStatementTextText |
1112 vfrStatementCheckBox |
1113 vfrStatementNumeric |
1116 vfrStatementPassword |
1117 vfrStatementString |
1118 vfrStatementSuppressIf |
1119 vfrStatementHidden |
1121 vfrStatementGrayOutIf |
1122 vfrStatementInconsistentIf |
1124 vfrStatementBanner |
1125 vfrStatementInventory |
1126 vfrStatementOrderedList |
1128 vfrStatementSaveRestoreDefaults
1131 //*****************************************************************************
1137 OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>
1139 WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
1140 AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
1145 //*****************************************************************************
1148 // oem 0x12, 0x34, 0x56;
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); >> )*
1157 //*****************************************************************************
1160 // inconsistentif NOT .... AND NOT .... OR ... endif;
1162 vfrStatementInconsistentIf :
1163 << ResetFlags (); >>
1164 IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>
1165 Prompt "=" getStringId ","
1167 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1169 << WriteFlags (); >> // write the flags field
1170 vfrBooleanExpression
1171 EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>
1174 //*****************************************************************************
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)
1182 // For supporting complex express, divide the vfrBooleanExpression to two parts
1183 // so that pred-LL(k) parser can parse incrementally.
1185 vfrBooleanExpression :
1186 leftPartVfrBooleanExp { rightPartVfrBooleanExp }
1189 leftPartVfrBooleanExp :
1190 OpenParen vfrBooleanExpression CloseParen |
1191 (ideqval | ideqid | ideqvallist | vareqval | truefalse) |
1192 NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
1195 rightPartVfrBooleanExp :
1196 AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> |
1197 OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>
1200 //*****************************************************************************
1206 TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |
1207 FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>
1210 //*****************************************************************************
1213 // varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};
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 ","
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 ()
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());
1246 //*****************************************************************************
1249 // vareqval var(0x100) == 0x20
1252 OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>
1254 VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>
1260 OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>
1261 vfrStructFieldName[0]
1265 //*****************************************************************************
1268 // ideqid MyNVData3.Field16A == MyNVData3.Field16B
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.
1274 OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >>
1275 vfrStructFieldName[0]
1276 compareVfrStructFieldNameNL0
1279 //*****************************************************************************
1281 // compareNumber is the combination of compare operation and Number
1286 VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>
1290 VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));
1291 WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
1295 VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));
1296 WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
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); >>
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); >>
1312 //*****************************************************************************
1314 // compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0]
1316 compareVfrStructFieldNameNL0 :
1318 "==" << mIdEqIdStmt = 1; >>
1319 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >>
1322 GTOPID:GreaterThan << mIdEqIdStmt = 1; >>
1323 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1324 WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
1327 GEOPID:GreaterEqual << mIdEqIdStmt = 1; >>
1328 vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
1329 WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
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); >>
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); >>
1347 OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>
1348 vfrStructFieldName[0]
1350 ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +
1351 << FlushQueueIdEqValList(); >>
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());
1360 KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >>
1361 Help "=" getStringId
1364 FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1367 "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1369 << WriteFlagsKey (KeyValue, LineNum); >>
1373 vfrStatementHidden :
1374 IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>
1376 VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>
1378 KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>
1382 //*****************************************************************************
1385 // suppressif <boolean_expression> { grayoutif } <statements>+ endif;
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
1392 vfrStatementSuppressIf :
1393 << ResetFlags (); >>
1394 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
1396 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1398 << WriteFlags (); >> // write the flags field
1399 vfrBooleanExpression
1401 { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+
1402 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1406 // This is the form for a grayoutif nested in a suppressif statement
1408 suppressIfGrayOutIf :
1409 << ResetFlags (); >>
1410 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>
1412 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1414 << WriteFlags (); >> // write the flags field
1415 vfrBooleanExpression
1419 //*****************************************************************************
1422 // grayoutif { flags = n, } <boolean_expression> endif;
1424 // You can have: grayoutif:suppressif:statements:endif
1425 // grayoutif:statements:endif
1428 vfrStatementGrayOutIf :
1429 << ResetFlags (); >>
1430 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
1432 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1434 << WriteFlags (); >> // write the flags field
1435 vfrBooleanExpression
1437 { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+
1438 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1442 // This is the format for a suppressif nested in a grayoutif
1444 grayoutIfSuppressIf :
1445 << ResetFlags (); >>
1446 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>
1448 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1450 << WriteFlags (); >> // write the flags field
1451 vfrBooleanExpression
1456 // These are the VFR statements that are valid inside a suppressif or grayoutif statement.
1458 suppressIfAndGrayoutIfSubstatements :
1460 vfrStatementTextText |
1461 vfrStatementCheckBox |
1462 vfrStatementNumeric |
1465 vfrStatementPassword |
1466 vfrStatementString |
1467 vfrStatementHidden |
1470 vfrStatementInventory |
1471 vfrStatementOrderedList |
1472 vfrStatementSaveRestoreDefaults
1475 //*****************************************************************************
1479 // password varid = MyNvData.Password,
1480 // prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
1481 // help = STRING_TOKEN(STR_PASSWORD_HELP),
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(); >>
1494 FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
1497 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
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)); >>
1506 //*****************************************************************************
1510 // string varid = MyNv.String,
1511 // prompt = STRING_TOKEN(STR_STRING_PROMPT),
1512 // help = STRING_TOKEN(STR_STRING_HELP),
1513 // flags = INTERACTIVE,
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.
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(); >>
1530 flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1534 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
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); >>
1542 //*****************************************************************************
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)
1552 // step = 1, // step is option, and step=1 if not specified
1553 // default = 0; // default is optional, and default=minimum if not specified
1556 // Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.
1557 // That check is done in WriteFlagsKey() function.
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(); >>
1566 FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >>
1569 Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1571 << WriteFlagsKey (KeyValue, LineNum); >>
1573 EndNumeric ";" << WriteMinMaxStepDefault (); >>
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)
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()); >> }
1591 //*****************************************************************************
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),
1603 // month varid = Date.Month,
1604 // prompt = STRING_TOKEN(STR_DATE_PROMPT),
1605 // help = STRING_TOKEN(STR_DATE_MONTH_HELP),
1611 // day varid = Date.Day,
1612 // prompt = STRING_TOKEN(STR_DATE_PROMPT),
1613 // help = STRING_TOKEN(STR_DATE_DAY_HELP),
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
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
1649 //*****************************************************************************
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;
1657 vfrStatementTextText :
1658 << ResetFlags (); >>
1659 IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>
1660 Help "=" getStringId ","
1662 getStringId // writes string identifier
1663 { "," Text "=" getStringId
1664 "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >>
1666 Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>
1671 //*****************************************************************************
1675 // inventory help = ID, text = ID;
1676 // inventory help = ID, text = id, text = ID;
1678 vfrStatementInventory :
1679 IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>
1680 Help "=" getStringId ","
1681 Text "=" getStringId // writes string identifier
1682 { "," Text "=" getStringId
1687 //*****************************************************************************
1691 // restore defaults,
1693 // prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
1694 // help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
1700 // prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
1701 // help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
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); >>
1711 FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2));
1712 AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());
1714 Prompt "=" getStringId ","
1715 KH:Help "=" getStringId << LineNum = KH->getLine(); >>
1717 "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
1720 "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
1722 << WriteFlagsKey (KeyValue, LineNum); >>
1726 //*****************************************************************************
1730 // flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
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()); >>
1743 dateTimeSubStatement :
1744 Prompt "=" getStringId ","
1745 Help "=" getStringId ","
1746 << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
1747 minMaxStepDefault << WriteMinMaxStepDefault (); >>
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(); >>
1758 Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>
1760 << WriteFlagsKey (KeyValue, LineNum); >>
1764 vfrStatementSubTitle :
1765 IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>
1766 getStringId // writes string indentifier
1770 //*****************************************************************************
1774 // title = STRING_TOKEN(STR_BANNER_TITLE),
1776 // align center; // or left or right
1779 // title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;
1781 vfrStatementBanner :
1782 IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>
1783 Title "=" getStringId ","
1785 Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>
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); >>
1792 Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>
1793 << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>
1797 //*****************************************************************************
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),
1805 // flags = DEFAULT | INTERACTIVE;
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.
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); >>
1821 //*****************************************************************************
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 --
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()); >>
1842 //*****************************************************************************
1846 // option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
1848 // Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to
1849 // be set, and value cannot be 0.
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);
1859 WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2));
1862 FF:Flags "=" orderedListFlagsField
1863 ("\|" orderedListFlagsField )*
1865 "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
1867 << WriteFlagsKey (KeyValue, FF->getLine()); >>
1868 ";" << mOptionCount++; >>
1871 //*****************************************************************************
1875 // flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
1877 // The ordered list flags field cannot have a default.
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); >>
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.
1896 vfrStructFieldNameArray[int FieldWidth] :
1897 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1898 SName:StringIdentifier
1900 SFieldName:StringIdentifier
1901 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1903 WriteFieldOffset (1,
1906 SFieldName->getText(),
1907 SFieldName->getLine(),
1917 // Parse references to VFR structure field names of form "MyNvStructure.Field",
1918 // then call a function to write out its offset and length.
1920 vfrStructFieldName[int FieldWidth] :
1921 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1922 SName:StringIdentifier
1924 SFieldName:StringIdentifier
1925 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1927 WriteFieldOffset (1,
1930 SFieldName->getText(),
1931 SFieldName->getLine(),
1940 //*****************************************************************************
1944 // MyNvStructure.FieldName[4]
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.
1949 vfrStructFieldNameNL[int FieldWidth] :
1950 << int ArrayIndex = 1; char IsArrayIndex = 0; >>
1951 SName:StringIdentifier
1953 SFieldName:StringIdentifier
1954 { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
1956 WriteFieldOffset (0,
1959 SFieldName->getText(),
1960 SFieldName->getLine(),
1969 //*****************************************************************************
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;
1979 suppressIfOptionText |
1980 grayOutIfOptionText |
1984 suppressIfOptionText :
1985 << ResetFlags (); >>
1986 OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
1988 FF:Flags "=" flagsField ( "\|" flagsField )* ","
1990 << WriteFlags (); >> // write the flags field
1991 vfrBooleanExpression
1993 { suppressIfGrayOutIf } ( commonOptionText )+
1994 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
1997 grayOutIfOptionText :
1998 << ResetFlags (); >>
1999 OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
2001 FF:Flags "=" flagsField ( "\|" flagsField )* ","
2003 << WriteFlags (); >> // write the flags field
2004 vfrBooleanExpression
2006 { grayoutIfSuppressIf } ( commonOptionText )+
2007 ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
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 )*
2017 "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
2019 << WriteFlagsKey (KeyValue, FF->getLine()); >>
2020 ";" << mOptionCount++; >>
2024 // Gets a string identifier. It must be a numeric value of form:
2026 // STRING_TOKEN(100)
2029 << unsigned short StrId; >>
2030 StringToken OpenParen
2031 IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >>
2035 //******************************************************************************
2037 // Parser class definition.
2039 class EfiVfrParser {
2042 // Parser definitions go here
2045 STRUCT_DEFINITION *mFirstStructDefinition;
2046 STRUCT_DEFINITION *mLastStructDefinition;
2047 INT32 mNvDataStructSize;
2048 INT32 mNonNvDataStructSize;
2050 // Flag to indicate that we're processing a ideqid VFR statement so that
2051 // we can do late checks on the statement.
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;
2065 UINT32 mSubStmtFlags;
2066 UINT32 mSubStmtFlagsLineNum;
2067 EFI_GUID mFormSetGuid;
2068 UINT8 mNvDataStructDefined;
2069 UINT16 mClass, mSubclass;
2071 UINT32 mOptionCount; // how many "option" fields in a given statement
2072 UINT32 mLastVarIdSize;
2077 EfiVfrParser::SetIfStart (
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.
2088 LineNum - source line number where the "if" was parsed.
2098 EfiVfrParser::SetClass (
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.
2109 LineNum - source line number where the class statement was parsed.
2110 Value - the class value
2117 if (Value & 0xFFFF0000) {
2118 PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
2120 mClass |= (UINT16)Value;
2123 EfiVfrParser::SetSubclass (
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.
2134 LineNum - source line number where the class statement was parsed.
2135 Value - the subclass value from the VFR statement
2142 if (Value & 0xFFFF0000) {
2143 PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
2145 mSubclass |= (UINT16)Value;
2147 VOID EfiVfrParser::WriteClass ()
2152 VOID EfiVfrParser::WriteSubclass ()
2154 WriteWord (mSubclass);
2157 VOID EfiVfrParser::WriteIfrBytes ()
2159 mOpcodeHandler.WriteIfrBytes ();
2162 EfiVfrParser::WriteFlagsKey (
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.
2176 KeyValue - the key value from the VFR statement
2177 LineNum - source line number where the statement was parsed
2184 if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {
2185 PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");
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;
2192 WriteWord (KeyValue);
2195 EfiVfrParser::InitOrderedList ()
2200 EfiVfrParser::EndOrderedList (
2204 if (mLastVarIdSize < mOptionCount) {
2205 PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
2209 EfiVfrParser::ResetFlags ()
2212 Routine Description:
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.
2229 mSubStmtFlagsLineNum = 0;
2233 // Test validity of flags value for a one-of statement.
2236 EfiVfrParser::TestOneOfFlags (
2241 // One of the fields must have had the default bit set
2243 if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {
2244 PrintWarningMessage (LineNum, "default value must be specified", NULL);
2248 EfiVfrParser::SetFlags (
2254 // Check for redefinitions and invalid combinations
2256 if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {
2257 PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");
2259 if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {
2260 PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");
2262 mSubStmtFlags |= Flags;
2263 mSubStmtFlagsLineNum = LineNum;
2266 EfiVfrParser::WriteFlags ()
2269 // Check value for validity
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);
2279 WriteByte ((UINT8)mSubStmtFlags, 'F');
2281 // We can now clear the substatement flags
2283 mStmtFlags |= mSubStmtFlags;
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.
2291 EfiVfrParser::InitMinMaxStepDefault ()
2299 EfiVfrParser::WriteMinMaxStepDefault ()
2301 WriteWord (mMinimumValue);
2302 WriteWord (mMaximumValue);
2303 WriteWord (mStepValue);
2304 WriteWord (mDefaultValue);
2307 EfiVfrParser::SetMinMaxStepDefault (
2318 mMinimumValue = Value;
2319 mDefaultValue = Value;
2323 } else if (MMSD == 1) {
2324 mMaximumValue = Value;
2326 // If min > max, then swap the values. That includes resetting the default
2329 if (mMinimumValue > mMaximumValue) {
2330 PrintWarningMessage (LineNum, NULL, "maximum < minimum");
2332 mMaximumValue = mMinimumValue;
2333 mMinimumValue = TempValue;
2334 mDefaultValue = mMinimumValue;
2339 } else if (MMSD == 2) {
2342 // Default specified. Make sure min <= default <= max.
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");
2352 PrintErrorMessage (LineNum, "application error", "internal MMSD error");
2356 EfiVfrParser::AddLabel (
2364 // Added a label from the user VFR script. Make sure they haven't already
2365 // defined the same label elsewhere
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");
2374 Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
2375 if (Label == NULL) {
2376 PrintErrorMessage (0, NULL, "memory allocation error");
2379 memset ((char *)Label, 0, sizeof (UINT16_LIST));
2380 Label->Value = LabelNumber;
2381 Label->LineNum = LineNum;
2382 Label->Next = mDefinedLabels;
2383 mDefinedLabels = Label;
2386 EfiVfrParser::QueueIdEqValList (
2392 U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
2394 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");
2396 memset ((char *)U16, 0, sizeof (UINT16_LIST));
2398 if (mUint16List == NULL) {
2401 mLastUint16->Next = U16;
2407 EfiVfrParser::FlushQueueIdEqValList ()
2412 // We queued up a list of IdEqValList items. The IFR requires a count
2413 // followed by the actual values. Do it.
2416 mLastUint16 = mUint16List;
2417 while (mLastUint16 != NULL) {
2419 mLastUint16 = mLastUint16->Next;
2421 // BUGBUG -- check for more than 16K items?
2424 // Now write the values.
2426 mLastUint16 = mUint16List;
2427 while (mLastUint16 != NULL) {
2428 WriteWord ((UINT32)mLastUint16->Value);
2429 mLastUint16 = mLastUint16->Next;
2434 mLastUint16 = mUint16List;
2435 while (mUint16List != NULL) {
2436 mLastUint16 = mUint16List->Next;
2438 mUint16List = mLastUint16;
2442 EfiVfrParser::PrintErrorMessage (
2451 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2452 Error (FileName, LineNum, 0, Msg1, Msg2);
2454 Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);
2458 EfiVfrParser::PrintWarningMessage (
2467 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2468 Warning (FileName, LineNum, 0, Msg1, Msg2);
2470 Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);
2475 ANTLRAbstractToken *Tok,
2478 ANTLRTokenType ETok,
2483 Routine Description:
2484 Called by the parser base class as a result of parse syntax errors.
2487 Tok - token that caused the error
2489 Eset - index in token table of the expected token
2500 LineNum = Tok->getLine ();
2501 FileName = ConvertLineNumber ((UINT32 *)&LineNum);
2503 // Sometimes the token number is 0, in which case I don't know what to
2507 Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");
2510 // If we were expecting an endif, then report the line where the corresponding
2513 if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {
2515 FileName = ConvertLineNumber (&LineNum);
2516 Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);
2518 Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);
2524 EfiVfrParser::init()
2527 Routine Description:
2528 Initializations function for our parser.
2538 ANTLRParser::init();
2541 // Used for queuing a variable list of UINT16's
2545 mFirstStructDefinition = NULL;
2546 mLastStructDefinition = NULL;
2547 mNvDataStructSize = 0;
2548 mNonNvDataStructSize = 0;
2549 mNvDataStructDefined = 0;
2550 mGotoReferences = NULL;
2551 mFormIdValues = NULL;
2552 mDefinedLabels = NULL;
2556 mDefinedVarStoreId = NULL;
2557 mLastDefinedVarStoreId = NULL;
2559 mLastNVVariableDataSize = 0;
2561 memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));
2564 // Destructor for the parser.
2566 EfiVfrParser::~EfiVfrParser(VOID)
2571 EfiVfrParser::Cleanup (VOID)
2574 Routine Description:
2575 Free memory allocated during parsing
2585 STRUCT_DEFINITION *NextStruct;
2586 STRUCT_FIELD_DEFINITION *NextField;
2588 UINT16_LIST *NextU16List;
2591 // Free up the structure definitions if any
2593 while (mFirstStructDefinition != NULL) {
2595 // Free up all the fields for this struct
2597 while (mFirstStructDefinition->Field != NULL) {
2598 NextField = mFirstStructDefinition->Field->Next;
2599 free (mFirstStructDefinition->Field->Name);
2600 free (mFirstStructDefinition->Field);
2601 mFirstStructDefinition->Field = NextField;
2603 NextStruct = mFirstStructDefinition->Next;
2604 free (mFirstStructDefinition->Name);
2605 free (mFirstStructDefinition);
2606 mFirstStructDefinition = NextStruct;
2609 // Free up the goto references and form id defines
2611 FreeGotoReferences ();
2613 // Free up label list
2615 while (mDefinedLabels != NULL) {
2616 NextU16List = mDefinedLabels->Next;
2617 delete (mDefinedLabels);
2618 mDefinedLabels = NextU16List;
2621 // Free up the list of defined variable storage IDs
2623 while (mDefinedVarStoreId != NULL) {
2624 NextU16List = mDefinedVarStoreId->Next;
2625 delete (mDefinedVarStoreId);
2626 mDefinedVarStoreId = NextU16List;
2631 EfiVfrParser::AtoX (
2638 Routine Description:
2639 Given a pointer to a ascii hex string, convert to a number with the given
2643 HexString - pointer to a string of format 30BCA
2644 Size - number of bytes to convert
2645 HexValue - return result
2648 The number of bytes converted.
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;
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;
2678 *HexValue = (*HexValue << 4) | Value;
2685 EfiVfrParser::WriteGuidValue (
2686 UINT32 TokenLineNum,
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 }
2705 Write out the value.
2708 TokenLineNum - line number where the guid was used
2709 G1-G11 - the 11 fields of the guid value
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);
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);
2744 EfiVfrParser::WriteFieldOffset (
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.
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
2777 STRUCT_DEFINITION *StructDef;
2778 STRUCT_FIELD_DEFINITION *FieldDef;
2783 // If we're writing an array size, then they better have referenced the field without an
2786 if (WriteArraySize && IsArrayIndex) {
2787 sprintf (Msg, "array index specified where an array is required");
2788 PrintErrorMessage (LineNum2, FieldName, Msg);
2792 // Look through our list of known structures for a match
2794 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
2796 // Check for matching structure name
2798 if (strcmp (StructDef->Name, StructName) == 0) {
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.
2804 StructDef->Referenced++;
2805 if (StructDef->VarStoreIdValid == 0) {
2807 // Set it valid so we don't flag it multiple times, then emit the error
2809 StructDef->VarStoreIdValid = 1;
2810 PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");
2813 // Let the opcode-handler know which variable storage we're now using
2816 mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);
2818 mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);
2821 // Found matching structure name. Now find the matching field name
2823 for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
2824 if (strcmp (FieldDef->Name, FieldName) == 0) {
2826 // Make sure the variable size is valid
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);
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
2839 VarSize = FieldDef->DataSize;
2840 if (FieldDef->IsArray == 0) {
2841 PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");
2844 if (FieldDef->ArrayLength < ArrayIndex) {
2845 PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");
2849 if (FieldDef->IsArray) {
2850 VarSize = FieldDef->DataSize * FieldDef->ArrayLength;
2852 VarSize = FieldDef->DataSize;
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.
2861 if (mLastVarIdSize != VarSize) {
2862 PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");
2866 mLastVarIdSize = VarSize;
2868 // If we're supposed to write an array size, then require it to be an array
2870 if (WriteArraySize && !FieldDef->IsArray) {
2871 PrintErrorMessage (LineNum2, FieldName, "array required");
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.
2878 Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);
2879 if (StructDef->IsNonNV) Offset += mNvDataStructSize;
2882 if (WriteArraySize) {
2883 if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {
2884 PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");
2887 WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);
2889 WriteByte (FieldDef->DataSize, 0);
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);
2902 // The structure was not found in the defined list. See if it's the "Date" structure
2904 if (strcmp (StructName, "Date") == 0) {
2906 // BUGBUG -- remove support for Date and Time as valid structure
2907 // names. They should use the NON_NV_DATA_MAP structure for this.
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.
2913 if (strcmp (FieldName, "Year") == 0) {
2915 // Write ID (offset), ID, and size
2917 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);
2921 } else if (strcmp (FieldName, "Month") == 0) {
2923 // Write ID (offset), ID, and size
2925 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);
2929 } else if (strcmp (FieldName, "Day") == 0) {
2931 // Write ID (offset), ID, and size
2933 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);
2938 PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");
2941 } else if (strcmp (StructName, "Time") == 0) {
2943 // Someone specified Time.Hours|Minutes|Seconds
2944 // BUGBUG -- define some constants for the IDs used here
2946 if (strcmp (FieldName, "Hours") == 0) {
2948 // Write ID (offset), ID, and size
2950 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);
2954 } else if (strcmp (FieldName, "Minutes") == 0) {
2956 // Write ID (offset), ID, and size
2958 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);
2962 } else if (strcmp (FieldName, "Seconds") == 0) {
2964 // Write ID (offset), ID, and size
2966 WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);
2971 PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");
2975 PrintErrorMessage (LineNum1, StructName, "undefined structure");
2980 EfiVfrParser::StartStructDefinition (
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.
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.
2999 STRUCT_DEFINITION *StructDef;
3001 // Allocate memory for the structure record
3003 StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));
3004 memset (StructDef, 0, sizeof (STRUCT_DEFINITION));
3005 StructDef->LineNum = LineNum;
3007 // Set flag indicating non-NV data structure or not
3009 StructDef->IsNonNV = IsNonNV;
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.
3014 if (mFirstStructDefinition == NULL) {
3015 mFirstStructDefinition = StructDef;
3016 StructDef->VarStoreIdValid = 1;
3018 mLastStructDefinition->Next = StructDef;
3020 mLastStructDefinition = StructDef;
3023 EfiVfrParser::EndStructDefinition (
3028 STRUCT_DEFINITION *StructDef;
3029 STRUCT_FIELD_DEFINITION *FieldDef;
3032 // Make sure they have not already defined a structure with this name
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");
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.
3045 // Allocate memory for the structure name
3047 mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);
3048 strcpy (mLastStructDefinition->Name, StructName);
3050 // Compute the structure size, and the offsets to each field
3053 for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
3054 FieldDef->Offset = Offset;
3055 Offset += FieldDef->ArrayLength * FieldDef->DataSize;
3057 mLastStructDefinition->Size = Offset;
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.
3063 if (mNonNvDataStructSize == 0) {
3064 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3065 if (StructDef->IsNonNV) {
3066 mNonNvDataStructSize = StructDef->Size;
3071 if (mNvDataStructSize == 0) {
3072 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3073 if (StructDef->IsNonNV == 0) {
3074 mNvDataStructSize = StructDef->Size;
3081 EfiVfrParser::AddStructField (
3090 Routine Description:
3091 We're parsing the VFR structure definition. Add another defined field to
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
3106 STRUCT_FIELD_DEFINITION *FieldDef;
3107 STRUCT_FIELD_DEFINITION *Temp;
3109 // Make sure we don't already have a field of this name in our structure
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");
3118 // If it's an array, then they better not have a size of 0. For example:
3119 // UINT8 MyBytes[0];
3121 if (IsArray && (ArrayLength <= 0)) {
3122 PrintErrorMessage (LineNum, FieldName, "invalid array size");
3126 // Allocate memory for a new structure field definition
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);
3136 // Add it to the end of the field list for the currently active structure
3138 if (mLastStructDefinition->Field == NULL) {
3139 mLastStructDefinition->Field = FieldDef;
3141 mLastStructDefinition->LastField->Next = FieldDef;
3143 mLastStructDefinition->LastField = FieldDef;
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)
3154 Routine Description:
3155 Called while parsing a varstore statement. Add the variable store
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
3169 STRUCT_DEFINITION *StructDef;
3170 UINT16_LIST *L16Ptr;
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.
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);
3182 // Key value of 0 is invalid since that's assigned by default to the default
3183 // variable store (the first structure parsed).
3185 if (VarStoreId == 0) {
3186 PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);
3189 // Create a new element to add to the list
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;
3198 mLastDefinedVarStoreId->Next = L16Ptr;
3200 mLastDefinedVarStoreId = L16Ptr;
3202 // Find the structure definition with this name
3204 for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
3205 if (strcmp (StructDef->Name, StructName) == 0) {
3207 // Make sure they did not already define a variable storage ID
3208 // for this structure.
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");
3214 StructDef->VarStoreId = VarStoreId;
3215 StructDef->VarStoreIdValid = 1;
3216 StructDef->VarStoreLineNum = LineNum;
3217 WriteWord (StructDef->Size);
3219 WriteByte(*VarName, 0);
3226 PrintErrorMessage (LineNum, StructName, "structure with this name not defined");
3229 EfiVfrParser::WriteDWord (
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.
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.
3251 // Write 4 bytes, little endian. Specify a key byte only on the first one
3253 mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);
3255 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3257 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3259 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3262 EfiVfrParser::WriteOpByte (
3268 Routine Description:
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).
3275 ByteValue - opcode value
3283 mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
3286 EfiVfrParser::WriteByte (
3292 Routine Description:
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.
3300 ByteValue - raw byte to write
3301 Key - character to tag the byte with when we write ByteValue to the
3310 mOpcodeHandler.AddByte (ByteValue, Key);
3313 EfiVfrParser::WriteWord (
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.
3323 Value - value to write.
3330 mOpcodeHandler.AddByte ((UINT8)Value, 0);
3331 mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
3334 EfiVfrParser::WriteStringIdWord (
3338 mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
3339 mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
3342 EfiVfrParser::FreeGotoReferences ()
3345 Routine Description:
3346 Called during cleanup to free up the memory we allocated when
3347 keeping track of VFR goto statements.
3357 GOTO_REFERENCE *CurrRef;
3358 GOTO_REFERENCE *NextRef;
3359 FORM_ID_VALUE *CurrFormId;
3360 FORM_ID_VALUE *NextFormId;
3365 // Go through all the "goto" references and make sure there was a
3366 // form ID of that value defined.
3368 for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {
3370 for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {
3371 if (CurrRef->Value == CurrFormId->Value) {
3377 sprintf (Name, "%d", (UINT32)CurrRef->Value);
3378 PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");
3382 // Now free up the form id and goto references
3384 CurrFormId = mFormIdValues;
3385 while (CurrFormId != NULL) {
3386 NextFormId = CurrFormId->Next;
3388 CurrFormId = NextFormId;
3390 mFormIdValues = NULL;
3391 CurrRef = mGotoReferences;
3392 while (CurrRef != NULL) {
3393 NextRef = CurrRef->Next;
3397 mGotoReferences = NULL;
3400 EfiVfrParser::AddGotoReference (
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.
3412 GotoNumber - the label number referenced
3413 LineNum - the line number where the reference was made (used for
3421 GOTO_REFERENCE *NewRef;
3423 NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));
3424 if (NewRef == NULL) {
3425 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
3428 memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));
3429 NewRef->Value = (UINT16)GotoNumber;
3430 NewRef->RefLineNum = LineNum;
3431 NewRef->Next = mGotoReferences;
3432 mGotoReferences = NewRef;
3435 EfiVfrParser::AddFormId (
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
3449 Note that formid = 0 is invalid.
3452 FormIdValue - the parsed value for the Form ID
3453 LineNum - line number of the source file we're parsing
3460 FORM_ID_VALUE *NewFormId;
3465 // Verify that FormId != 0
3467 if (FormIdValue == 0) {
3468 FileName = ConvertLineNumber (&LineNum);
3469 Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);
3473 // First go through all previously defined form IDs and make sure they have not defined
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);
3487 // Allocate memory for a new one
3489 NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));
3490 if (NewFormId == NULL) {
3491 Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
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;
3501 EfiVfrParser::GetNumber (
3509 if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {
3510 AtoX (NumStr + 2, 4, &Value);
3512 Value = (UINT32)atoi (NumStr);
3517 if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {
3518 PrintErrorMessage (LineNum, NumStr, "value out of range");
3526 } // end grammar class