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