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