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