]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CodeTools/Source/VfrCompile/VfrServices.cpp
More renames for Tool Packages
[mirror_edk2.git] / Tools / CodeTools / Source / VfrCompile / VfrServices.cpp
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 VfrServices.cpp\r
15\r
16Abstract:\r
17\r
18 Support routines for the VFR compiler\r
19 \r
20--*/ \r
21\r
22#include <stdio.h> // for FILE routines\r
23#include <stdlib.h> // for malloc() and free()\r
24\r
ce53a8c3 25#include <Common/UefiBaseTypes.h>\r
26#include <Common/MultiPhase.h>\r
27#include <Common/InternalFormRepresentation.h>\r
28#include <Protocol/UgaDraw.h> // for EFI_UGA_PIXEL definition\r
29#include <Protocol/Hii.h>\r
30\r
878ddf1f 31#include "EfiUtilityMsgs.h"\r
32#include "EfiVfr.h"\r
33#include "VfrServices.h"\r
34\r
878ddf1f 35\r
36static const char *mSourceFileHeader[] = {\r
37 "//",\r
38 "// DO NOT EDIT -- auto-generated file",\r
39 "//",\r
40 "// This file is generated by the VFR compiler.",\r
41 "//",\r
42 NULL\r
43};\r
44\r
45typedef struct {\r
46 CHAR8 *Name;\r
47 INT32 Size;\r
48} IFR_OPCODE_SIZES;\r
49\r
50//\r
51// Create a table that can be used to do internal checking on the IFR\r
52// bytes we emit.\r
53//\r
54static const IFR_OPCODE_SIZES mOpcodeSizes[] = {\r
55 { 0, 0 }, // invalid\r
56 { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },\r
57 { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) }, \r
58 { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) }, \r
59 { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP\r
60 { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) }, \r
61 { "EFI_IFR_CHECKBOX", sizeof (EFI_IFR_CHECKBOX) }, \r
62 { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) }, \r
63 { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) }, \r
64 { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) }, \r
65 { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) }, \r
66 { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) }, \r
67 { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) }, \r
68 { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) }, \r
69 { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) }, \r
70 { "EFI_IFR_REF", sizeof (EFI_IFR_REF) }, \r
71 { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) }, \r
72 { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) }, \r
73 { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) }, \r
74 { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) }, \r
75 { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) }, \r
76 { "EFI_IFR_AND", sizeof (EFI_IFR_AND) }, \r
77 { "EFI_IFR_OR", sizeof (EFI_IFR_OR) }, \r
78 { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) }, \r
79 { "EFI_IFR_END_EXPR", sizeof (EFI_IFR_END_EXPR) }, \r
80 { "EFI_IFR_GRAY_OUT", sizeof (EFI_IFR_GRAY_OUT) }, \r
81 { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 }, \r
82 { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 }, \r
83 { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) }, \r
84 { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) }, \r
85 { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) }, \r
86 { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) }, \r
87 { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },\r
88 { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },\r
89 { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },\r
90 { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },\r
91 { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },\r
92 { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },\r
93 { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },\r
94 { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},\r
95 { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},\r
96 { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},\r
97 { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},\r
98 { "EFI_IFR_OEM_DEFINED_OP", -2 },\r
99};\r
100\r
101\r
102VfrOpcodeHandler::VfrOpcodeHandler (\r
103 ) \r
104/*++\r
105\r
106Routine Description:\r
107 Constructor for the VFR opcode handling class.\r
108 \r
109Arguments:\r
110 None\r
111\r
112Returns:\r
113 None\r
114\r
115--*/\r
116{ \r
117 mIfrBytes = NULL; \r
118 mLastIfrByte = NULL;\r
119 mBytesWritten = 0;\r
120 mQueuedByteCount = 0;\r
121 mQueuedOpcodeByteValid = 0;\r
122 mPrimaryVarStoreId = 0;\r
123 mSecondaryVarStoreId = 0;\r
124 mSecondaryVarStoreIdSet = 0;\r
125 mPrimaryVarStoreIdSet = 0;\r
126 mDefaultVarStoreId = 0;\r
127}\r
128\r
129VOID \r
130VfrOpcodeHandler::SetVarStoreId (\r
131 UINT16 VarStoreId\r
132 )\r
133/*++\r
134\r
135Routine Description:\r
136 This function is invoked by the parser when a variable is referenced in the \r
137 VFR. Save the variable store (and set a flag) so that we can later determine \r
138 if we need to emit a varstore-select or varstore-select-pair opcode.\r
139 \r
140Arguments:\r
141 VarStoreId - ID of the variable store referenced in the VFR\r
142\r
143Returns:\r
144 None\r
145\r
146--*/\r
147{\r
148 mPrimaryVarStoreId = VarStoreId;\r
149 mPrimaryVarStoreIdSet = 1;\r
150}\r
151\r
152VOID \r
153VfrOpcodeHandler::SetSecondaryVarStoreId (\r
154 UINT16 VarStoreId\r
155 )\r
156/*++\r
157\r
158Routine Description:\r
159 This function is invoked by the parser when a secondary variable is \r
160 referenced in the VFR. Save the variable store (and set a flag) so \r
161 that we can later determine if we need to emit a varstore-select or \r
162 varstore-pair opcode.\r
163 \r
164Arguments:\r
165 VarStoreId - ID of the variable store referenced in the VFR\r
166\r
167Returns:\r
168 None\r
169\r
170--*/\r
171{\r
172 mSecondaryVarStoreId = VarStoreId;\r
173 mSecondaryVarStoreIdSet = 1;\r
174}\r
175\r
176VOID \r
177VfrOpcodeHandler::WriteIfrBytes (\r
178 ) \r
179/*++\r
180\r
181Routine Description:\r
182 This function is invoked at the end of parsing. Its purpose\r
183 is to write out all the IFR bytes that were queued up while\r
184 parsing.\r
185 \r
186Arguments:\r
187 None\r
188\r
189Returns:\r
190 None\r
191\r
192--*/\r
193{ \r
194 IFR_BYTE *Curr;\r
195 IFR_BYTE *Next;\r
196 UINT32 Count;\r
197 UINT32 LineCount;\r
198 UINT32 PoundLines;\r
199 UINT32 ByteCount;\r
200 CHAR8 Line[MAX_LINE_LEN];\r
201 CHAR8 *Cptr;\r
202 FILE *InFptr;\r
203 FILE *OutFptr;\r
204 UINT32 ListFile;\r
205 EFI_HII_IFR_PACK_HEADER IfrHeader;\r
206 UINT8 *Ptr;\r
207 FILE *IfrBinFptr;\r
208 UINT32 BytesLeftThisOpcode;\r
209 //\r
210 // If someone added a new opcode and didn't update our opcode sizes structure, error out.\r
211 //\r
212 if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {\r
213 Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");\r
214 return;\r
215 }\r
216 //\r
217 // Flush the queue\r
218 //\r
219 FlushQueue (); \r
220 //\r
221 // If there have been any errors to this point, then skip dumping the IFR\r
222 // binary data. This way doing an nmake again will try to build it again, and\r
223 // the build will fail if they did not fix the problem.\r
224 //\r
225 if (GetUtilityStatus () != STATUS_ERROR) {\r
226 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {\r
227 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");\r
228 return;\r
229 }\r
230 //\r
231 // Write the standard file header to the output file\r
232 //\r
233 WriteStandardFileHeader (IfrBinFptr);\r
234 //\r
235 // Write the structure header\r
236 //\r
237 fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);\r
238 //\r
239 // Write the header\r
240 //\r
241 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));\r
242 IfrHeader.Header.Type = EFI_HII_IFR;\r
243 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); \r
244 Ptr = (UINT8 *)&IfrHeader;\r
245 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {\r
246 if ((Count & 0x03) == 0) {\r
247 fprintf (IfrBinFptr, "\n ");\r
248 }\r
249 fprintf (IfrBinFptr, "0x%02X, ", *Ptr); \r
250 }\r
251 //\r
252 //\r
253 // Write all the IFR bytes\r
254 //\r
255 fprintf (IfrBinFptr, "\n // start of IFR data");\r
256 Curr = mIfrBytes;\r
257 Count = 0;\r
258 while (Curr != NULL) {\r
259 if ((Count & 0x0F) == 0) {\r
260 fprintf (IfrBinFptr, "\n ");\r
261 }\r
262 if (Curr->KeyByte != 0) {\r
263 fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);\r
264 }\r
265 fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);\r
266 Count++;\r
267 Curr = Curr->Next;\r
268 }\r
269 fprintf (IfrBinFptr, "\n};\n\n");\r
270 //\r
271 //\r
272 // Close the file\r
273 //\r
274 fclose (IfrBinFptr); \r
275 IfrBinFptr = NULL;\r
276 }\r
277 //\r
278 // Write the bytes as binary data if the user specified to do so\r
279 //\r
280 if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {\r
281 //\r
282 // Use the Ifr output file name with a ".hpk" extension.\r
283 //\r
284 for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;\r
285 (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');\r
286 Cptr--) {\r
287 //\r
288 // do nothing\r
289 //\r
290 }\r
291 if (*Cptr == '.') {\r
292 strcpy (Cptr, ".hpk");\r
293 } else {\r
294 strcat (gOptions.IfrOutputFileName, ".hpk");\r
295 }\r
296 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {\r
297 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");\r
298 return;\r
299 }\r
300 //\r
301 // Write the structure header\r
302 //\r
303 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));\r
304 IfrHeader.Header.Type = EFI_HII_IFR;\r
305 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); \r
306 Ptr = (UINT8 *)&IfrHeader;\r
307 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {\r
308 fwrite (Ptr, 1, 1, IfrBinFptr);\r
309 }\r
310 //\r
311 //\r
312 // Write all the IFR bytes\r
313 //\r
314 Curr = mIfrBytes;\r
315 Count = 0;\r
316 while (Curr != NULL) {\r
317 fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);\r
318 Curr = Curr->Next;\r
319 }\r
320 //\r
321 //\r
322 // Close the file\r
323 //\r
324 fclose (IfrBinFptr); \r
325 IfrBinFptr = NULL;\r
326 }\r
327 //\r
328 // If creating a listing file, then open the input and output files\r
329 //\r
330 ListFile = 0;\r
331 if (gOptions.CreateListFile) {\r
332 //\r
333 // Open the input VFR file and the output list file\r
334 //\r
335 if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {\r
336 Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");\r
337 } else {\r
338 if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {\r
339 Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");\r
340 fclose (InFptr);\r
341 InFptr = NULL;\r
342 } else {\r
343 LineCount = 0;\r
344 ListFile = 1;\r
345 PoundLines = 0;\r
346 ByteCount = 0;\r
347 }\r
348 }\r
349 }\r
350 //\r
351 // Write the list file\r
352 //\r
353 if (ListFile) {\r
354 //\r
355 // Write out the VFR compiler version\r
356 //\r
357 fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
358 Curr = mIfrBytes;\r
359 while (Curr != NULL) {\r
360 //\r
361 // Print lines until we reach the line of the current opcode\r
362 //\r
363 while (LineCount < PoundLines + Curr->LineNum) {\r
364 if (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
365 //\r
366 // We should check for line length exceeded on the fgets(). Otherwise it\r
367 // throws the listing file output off. Future enhancement perhaps.\r
368 //\r
369 fprintf (OutFptr, "%s", Line);\r
370 if (strncmp (Line, "#line", 5) == 0) {\r
371 PoundLines++;\r
372 }\r
373 }\r
374 LineCount++;\r
375 }\r
376 //\r
377 // Print all opcodes with line numbers less than where we are now\r
378 //\r
379 BytesLeftThisOpcode = 0;\r
380 while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {\r
381 if (BytesLeftThisOpcode == 0) {\r
382 fprintf (OutFptr, ">%08X: ", ByteCount);\r
383 if (Curr->Next != NULL) {\r
384 BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;\r
385 }\r
386 }\r
387 fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);\r
388 ByteCount++;\r
389 BytesLeftThisOpcode--;\r
390 if (BytesLeftThisOpcode == 0) {\r
391 fprintf (OutFptr, "\n");\r
392 }\r
393 Curr = Curr->Next;\r
394 }\r
395 }\r
396 //\r
397 // Dump any remaining lines from the input file\r
398 //\r
399 while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
400 fprintf (OutFptr, "%s", Line);\r
401 }\r
402 fclose (InFptr);\r
403 fclose (OutFptr);\r
404 }\r
405 //\r
406 // Debug code to make sure that each opcode we write out has as many\r
407 // bytes as the IFR structure requires. If there were errors, then\r
408 // don't do this step.\r
409 //\r
410 if (GetUtilityStatus () != STATUS_ERROR) {\r
411 Curr = mIfrBytes;\r
412 ByteCount = 0;\r
413 while (Curr != NULL) {\r
414 //\r
415 // First byte is the opcode, second byte is the length\r
416 //\r
417 if (Curr->Next == NULL) {\r
418 Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");\r
419 break;\r
420 }\r
421 Count = (UINT32)Curr->Next->OpcodeByte;\r
422 if (Count == 0) {\r
423 Error (\r
424 __FILE__, \r
425 __LINE__, \r
426 0, \r
427 "application error", \r
428 "opcode with 0 length specified in output at offset 0x%X", \r
429 ByteCount\r
430 );\r
431 break;\r
432 }\r
433 //\r
434 // Check the length\r
435 //\r
436 if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {\r
437 Error (\r
438 __FILE__, \r
439 __LINE__, \r
440 0, \r
441 "application error", \r
442 "invalid opcode 0x%X in output at offset 0x%X", \r
443 (UINT32) Curr->OpcodeByte, ByteCount\r
444 );\r
445 } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {\r
446 //\r
447 // For those cases where the length is variable, the size is negative, and indicates\r
448 // the miniumum size.\r
449 //\r
450 if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {\r
451 Error (\r
452 __FILE__, \r
453 __LINE__, \r
454 0, \r
455 "application error", \r
456 "insufficient number of bytes written for %s at offset 0x%X",\r
457 mOpcodeSizes[Curr->OpcodeByte].Name, \r
458 ByteCount\r
459 );\r
460 }\r
461 } else {\r
462 //\r
463 // Check for gaps\r
464 //\r
465 if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {\r
466 Error (\r
467 __FILE__, \r
468 __LINE__, \r
469 0, \r
470 "application error", \r
471 "invalid opcode 0x%X in output at offset 0x%X", \r
472 (UINT32)Curr->OpcodeByte, \r
473 ByteCount\r
474 );\r
475 } else {\r
476 //\r
477 // Check size\r
478 //\r
479 if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {\r
480 Error (\r
481 __FILE__, \r
482 __LINE__, \r
483 0, \r
484 "application error", \r
485 "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",\r
486 Count, \r
487 mOpcodeSizes[Curr->OpcodeByte].Size, \r
488 mOpcodeSizes[Curr->OpcodeByte].Name, \r
489 ByteCount\r
490 );\r
491 }\r
492 }\r
493 }\r
494 //\r
495 // Skip to next opcode\r
496 //\r
497 while (Count > 0) {\r
498 ByteCount++;\r
499 if (Curr == NULL) {\r
500 Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");\r
501 break;\r
502 }\r
503 Curr = Curr->Next;\r
504 Count--;\r
505 }\r
506 }\r
507 }\r
508}\r
509\r
510VfrOpcodeHandler::~VfrOpcodeHandler(\r
511 ) \r
512/*++\r
513\r
514Routine Description:\r
515 Destructor for the VFR opcode handler. Free up memory allocated\r
516 while parsing the VFR script.\r
517 \r
518Arguments:\r
519 None\r
520\r
521Returns:\r
522 None\r
523\r
524--*/\r
525{\r
526 IFR_BYTE *Curr;\r
527 IFR_BYTE *Next;\r
528 //\r
529 // Free up the IFR bytes\r
530 //\r
531 Curr = mIfrBytes;\r
532 while (Curr != NULL) {\r
533 Next = Curr->Next;\r
534 free (Curr);\r
535 Curr = Next;\r
536 }\r
537}\r
538\r
539int \r
540VfrOpcodeHandler::AddOpcodeByte (\r
541 UINT8 OpcodeByte, \r
542 UINT32 LineNum\r
543 ) \r
544/*++\r
545\r
546Routine Description:\r
547 This function is invoked by the parser when a new IFR\r
548 opcode should be emitted.\r
549 \r
550Arguments:\r
551 OpcodeByte - the IFR opcode\r
552 LineNum - the line number from the source file that resulted\r
553 in the opcode being emitted.\r
554\r
555Returns:\r
556 0 always\r
557\r
558--*/\r
559{\r
560 UINT32 Count;\r
561\r
562 FlushQueue();\r
563 //\r
564 // Now add this new byte\r
565 //\r
566 mQueuedOpcodeByte = OpcodeByte;\r
567 mQueuedLineNum = LineNum;\r
568 mQueuedOpcodeByteValid = 1;\r
569 return 0;\r
570}\r
571\r
572VOID \r
573VfrOpcodeHandler::AddByte (\r
574 UINT8 ByteVal, \r
575 UINT8 KeyByte\r
576 )\r
577/*++\r
578\r
579Routine Description:\r
580 This function is invoked by the parser when it determines\r
581 that more raw IFR bytes should be emitted to the output stream.\r
582 Here we just queue them up into an output buffer.\r
583 \r
584Arguments:\r
585 ByteVal - the raw byte to emit to the output IFR stream\r
586 KeyByte - a value that can be used for debug. \r
587\r
588Returns:\r
589 None\r
590\r
591--*/\r
592{\r
593 //\r
594 // Check for buffer overflow\r
595 //\r
596 if (mQueuedByteCount > MAX_QUEUE_COUNT) {\r
597 Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");\r
598 } else {\r
599 mQueuedBytes[mQueuedByteCount] = ByteVal;\r
600 mQueuedKeyBytes[mQueuedByteCount] = KeyByte;\r
601 mQueuedByteCount++;\r
602 }\r
603}\r
604\r
605int \r
606VfrOpcodeHandler::FlushQueue (\r
607 )\r
608/*++\r
609\r
610Routine Description:\r
611 This function is invoked to flush the internal IFR buffer.\r
612 \r
613Arguments:\r
614 None\r
615\r
616Returns:\r
617 0 always\r
618\r
619--*/\r
620{\r
621 UINT32 Count;\r
622 UINT32 EmitNoneOnePair;\r
623\r
624 EmitNoneOnePair = 0;\r
625 //\r
626 // If the secondary varstore was specified, then we have to emit\r
627 // a varstore-select-pair opcode, which only applies to the following\r
628 // statement. \r
629 //\r
630 if (mSecondaryVarStoreIdSet) {\r
631 mSecondaryVarStoreIdSet = 0;\r
632 //\r
633 // If primary and secondary are the same as the current default\r
634 // varstore, then we don't have to do anything.\r
635 // Note that the varstore-select-pair only applies to the following\r
636 // opcode.\r
637 //\r
638 if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {\r
639 IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);\r
640 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);\r
641 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);\r
642 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);\r
643 IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);\r
644 IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);\r
645 }\r
646 } else if (mPrimaryVarStoreIdSet != 0) {\r
647 mPrimaryVarStoreIdSet = 0;\r
648 if (mDefaultVarStoreId != mPrimaryVarStoreId) {\r
649 //\r
650 // The VFR statement referenced a different variable store \r
651 // than the last one we reported. Insert a new varstore select \r
652 // statement. \r
653 //\r
654 IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);\r
655 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);\r
656 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);\r
657 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);\r
658 mDefaultVarStoreId = mPrimaryVarStoreId;\r
659 }\r
660 }\r
661 //\r
662 // Likely a new opcode is being added. Since each opcode item in the IFR has \r
663 // a header that specifies the size of the opcode item (which we don't\r
664 // know until we find the next opcode in the VFR), we queue up bytes\r
665 // until we know the size. Then we write them out. So flush the queue\r
666 // now.\r
667 //\r
668 if (mQueuedOpcodeByteValid != 0) {\r
669 // \r
670 // Add the previous opcode byte, the length byte, and the binary\r
671 // data.\r
672 //\r
673 IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);\r
674 IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);\r
675 for (Count = 0; Count < mQueuedByteCount; Count++) {\r
676 IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0); \r
677 }\r
678 mQueuedByteCount = 0;\r
679 mQueuedOpcodeByteValid = 0;\r
680 } \r
681 return 0;\r
682}\r
683\r
684int \r
685VfrOpcodeHandler::IAddByte (\r
686 UINT8 ByteVal, \r
687 UINT8 KeyByte, \r
688 UINT32 LineNum\r
689 )\r
690/*++\r
691\r
692Routine Description:\r
693 This internal function is used to add actual IFR bytes to\r
694 the output stream. Most other functions queue up the bytes\r
695 in an internal buffer. Once they come here, there's no\r
696 going back.\r
697\r
698 \r
699Arguments:\r
700 ByteVal - value to write to output \r
701 KeyByte - key value tied to the byte -- useful for debug\r
702 LineNum - line number from source file the byte resulted from\r
703\r
704Returns:\r
705 0 - if successful\r
706 1 - failed due to memory allocation failure\r
707\r
708--*/\r
709{\r
710 IFR_BYTE *NewByte;\r
711 NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));\r
712 if (NewByte == NULL) {\r
713 return 1;\r
714 }\r
715 memset ((char *)NewByte, 0, sizeof (IFR_BYTE));\r
716 NewByte->OpcodeByte = ByteVal;\r
717 NewByte->KeyByte = KeyByte;\r
718 NewByte->LineNum = LineNum;\r
719 //\r
720 // Add to the list\r
721 //\r
722 if (mIfrBytes == NULL) {\r
723 mIfrBytes = NewByte;\r
724 } else {\r
725 mLastIfrByte->Next = NewByte;\r
726 } \r
727 mLastIfrByte = NewByte;\r
728 mBytesWritten++;\r
729 return 0;\r
730}\r
731\r
732VOID \r
733WriteStandardFileHeader (\r
734 FILE *OutFptr\r
735 ) \r
736/*++\r
737\r
738Routine Description:\r
739 This function is invoked to emit a standard header to an\r
740 output text file.\r
741 \r
742Arguments:\r
743 OutFptr - file to write the header to\r
744\r
745Returns:\r
746 None\r
747\r
748--*/\r
749{\r
750 UINT32 TempIndex;\r
751 for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {\r
752 fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);\r
753 }\r
754 //\r
755 // Write out the VFR compiler version\r
756 //\r
757 fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
758}\r