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