Home | History | Annotate | Download | only in VfrCompile
      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 
     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
    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
    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
    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 
    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
    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
    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
    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
    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
    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