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