summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp')
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp754
1 files changed, 754 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp
new file mode 100644
index 0000000000..e9c54d3387
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp
@@ -0,0 +1,754 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VfrServices.cpp
+
+Abstract:
+
+ Support routines for the VFR compiler
+
+--*/
+
+#include <stdio.h> // for FILE routines
+#include <stdlib.h> // for malloc() and free()
+
+#include "Tiano.h"
+#include "EfiUtilityMsgs.h"
+#include "EfiVfr.h"
+#include "VfrServices.h"
+
+#include EFI_PROTOCOL_DEFINITION (Hii)
+
+static const char *mSourceFileHeader[] = {
+ "//",
+ "// DO NOT EDIT -- auto-generated file",
+ "//",
+ "// This file is generated by the VFR compiler.",
+ "//",
+ NULL
+};
+
+typedef struct {
+ INT8 *Name;
+ INT32 Size;
+} IFR_OPCODE_SIZES;
+
+//
+// Create a table that can be used to do internal checking on the IFR
+// bytes we emit.
+//
+static const IFR_OPCODE_SIZES mOpcodeSizes[] = {
+ { 0, 0 }, // invalid
+ { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },
+ { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) },
+ { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) },
+ { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP
+ { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) },
+ { "EFI_IFR_CHECK_BOX", sizeof (EFI_IFR_CHECK_BOX) },
+ { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) },
+ { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) },
+ { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) },
+ { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) },
+ { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) },
+ { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) },
+ { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) },
+ { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) },
+ { "EFI_IFR_REF", sizeof (EFI_IFR_REF) },
+ { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) },
+ { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) },
+ { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) },
+ { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) },
+ { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) },
+ { "EFI_IFR_AND", sizeof (EFI_IFR_AND) },
+ { "EFI_IFR_OR", sizeof (EFI_IFR_OR) },
+ { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) },
+ { "EFI_IFR_END_IF", sizeof (EFI_IFR_END_IF) },
+ { "EFI_IFR_GRAYOUT", sizeof (EFI_IFR_GRAYOUT) },
+ { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 },
+ { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 },
+ { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) },
+ { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) },
+ { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) },
+ { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) },
+ { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },
+ { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },
+ { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },
+ { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },
+ { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },
+ { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },
+ { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },
+ { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},
+ { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},
+ { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},
+ { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},
+ { "EFI_IFR_OEM_DEFINED_OP", -2 },
+};
+
+
+VfrOpcodeHandler::VfrOpcodeHandler (
+ )
+/*++
+
+Routine Description:
+ Constructor for the VFR opcode handling class.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ mIfrBytes = NULL;
+ mLastIfrByte = NULL;
+ mBytesWritten = 0;
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ mPrimaryVarStoreId = 0;
+ mSecondaryVarStoreId = 0;
+ mSecondaryVarStoreIdSet = 0;
+ mPrimaryVarStoreIdSet = 0;
+ mDefaultVarStoreId = 0;
+}
+
+VOID
+VfrOpcodeHandler::SetVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a variable is referenced in the
+ VFR. Save the variable store (and set a flag) so that we can later determine
+ if we need to emit a varstore-select or varstore-select-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mPrimaryVarStoreId = VarStoreId;
+ mPrimaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::SetSecondaryVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a secondary variable is
+ referenced in the VFR. Save the variable store (and set a flag) so
+ that we can later determine if we need to emit a varstore-select or
+ varstore-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mSecondaryVarStoreId = VarStoreId;
+ mSecondaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::WriteIfrBytes (
+ )
+/*++
+
+Routine Description:
+ This function is invoked at the end of parsing. Its purpose
+ is to write out all the IFR bytes that were queued up while
+ parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ UINT32 Count;
+ UINT32 LineCount;
+ UINT32 PoundLines;
+ UINT32 ByteCount;
+ INT8 Line[MAX_LINE_LEN];
+ INT8 *Cptr;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT32 ListFile;
+ EFI_HII_IFR_PACK_HEADER IfrHeader;
+ UINT8 *Ptr;
+ FILE *IfrBinFptr;
+ UINT32 BytesLeftThisOpcode;
+ //
+ // If someone added a new opcode and didn't update our opcode sizes structure, error out.
+ //
+ if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {
+ Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");
+ return;
+ }
+ //
+ // Flush the queue
+ //
+ FlushQueue ();
+ //
+ // If there have been any errors to this point, then skip dumping the IFR
+ // binary data. This way doing an nmake again will try to build it again, and
+ // the build will fail if they did not fix the problem.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the standard file header to the output file
+ //
+ WriteStandardFileHeader (IfrBinFptr);
+ //
+ // Write the structure header
+ //
+ fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);
+ //
+ // Write the header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ if ((Count & 0x03) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", *Ptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ fprintf (IfrBinFptr, "\n // start of IFR data");
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ if ((Count & 0x0F) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ if (Curr->KeyByte != 0) {
+ fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);
+ Count++;
+ Curr = Curr->Next;
+ }
+ fprintf (IfrBinFptr, "\n};\n\n");
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // Write the bytes as binary data if the user specified to do so
+ //
+ if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {
+ //
+ // Use the Ifr output file name with a ".hpk" extension.
+ //
+ for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;
+ (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');
+ Cptr--) {
+ //
+ // do nothing
+ //
+ }
+ if (*Cptr == '.') {
+ strcpy (Cptr, ".hpk");
+ } else {
+ strcat (gOptions.IfrOutputFileName, ".hpk");
+ }
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the structure header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ fwrite (Ptr, 1, 1, IfrBinFptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);
+ Curr = Curr->Next;
+ }
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // If creating a listing file, then open the input and output files
+ //
+ ListFile = 0;
+ if (gOptions.CreateListFile) {
+ //
+ // Open the input VFR file and the output list file
+ //
+ if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");
+ } else {
+ if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ LineCount = 0;
+ ListFile = 1;
+ PoundLines = 0;
+ ByteCount = 0;
+ }
+ }
+ }
+ //
+ // Write the list file
+ //
+ if (ListFile) {
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ //
+ // Print lines until we reach the line of the current opcode
+ //
+ while (LineCount < PoundLines + Curr->LineNum) {
+ if (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ //
+ // We should check for line length exceeded on the fgets(). Otherwise it
+ // throws the listing file output off. Future enhancement perhaps.
+ //
+ fprintf (OutFptr, "%s", Line);
+ if (strncmp (Line, "#line", 5) == 0) {
+ PoundLines++;
+ }
+ }
+ LineCount++;
+ }
+ //
+ // Print all opcodes with line numbers less than where we are now
+ //
+ BytesLeftThisOpcode = 0;
+ while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, ">%08X: ", ByteCount);
+ if (Curr->Next != NULL) {
+ BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;
+ }
+ }
+ fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);
+ ByteCount++;
+ BytesLeftThisOpcode--;
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, "\n");
+ }
+ Curr = Curr->Next;
+ }
+ }
+ //
+ // Dump any remaining lines from the input file
+ //
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ fprintf (OutFptr, "%s", Line);
+ }
+ fclose (InFptr);
+ fclose (OutFptr);
+ }
+ //
+ // Debug code to make sure that each opcode we write out has as many
+ // bytes as the IFR structure requires. If there were errors, then
+ // don't do this step.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ Curr = mIfrBytes;
+ ByteCount = 0;
+ while (Curr != NULL) {
+ //
+ // First byte is the opcode, second byte is the length
+ //
+ if (Curr->Next == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");
+ break;
+ }
+ Count = (UINT32)Curr->Next->OpcodeByte;
+ if (Count == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "opcode with 0 length specified in output at offset 0x%X",
+ ByteCount
+ );
+ break;
+ }
+ //
+ // Check the length
+ //
+ if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32) Curr->OpcodeByte, ByteCount
+ );
+ } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {
+ //
+ // For those cases where the length is variable, the size is negative, and indicates
+ // the miniumum size.
+ //
+ if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "insufficient number of bytes written for %s at offset 0x%X",
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ } else {
+ //
+ // Check for gaps
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32)Curr->OpcodeByte,
+ ByteCount
+ );
+ } else {
+ //
+ // Check size
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",
+ Count,
+ mOpcodeSizes[Curr->OpcodeByte].Size,
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ }
+ }
+ //
+ // Skip to next opcode
+ //
+ while (Count > 0) {
+ ByteCount++;
+ if (Curr == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");
+ break;
+ }
+ Curr = Curr->Next;
+ Count--;
+ }
+ }
+ }
+}
+
+VfrOpcodeHandler::~VfrOpcodeHandler(
+ )
+/*++
+
+Routine Description:
+ Destructor for the VFR opcode handler. Free up memory allocated
+ while parsing the VFR script.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ //
+ // Free up the IFR bytes
+ //
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ Next = Curr->Next;
+ free (Curr);
+ Curr = Next;
+ }
+}
+
+int
+VfrOpcodeHandler::AddOpcodeByte (
+ UINT8 OpcodeByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a new IFR
+ opcode should be emitted.
+
+Arguments:
+ OpcodeByte - the IFR opcode
+ LineNum - the line number from the source file that resulted
+ in the opcode being emitted.
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+
+ FlushQueue();
+ //
+ // Now add this new byte
+ //
+ mQueuedOpcodeByte = OpcodeByte;
+ mQueuedLineNum = LineNum;
+ mQueuedOpcodeByteValid = 1;
+ return 0;
+}
+
+VOID
+VfrOpcodeHandler::AddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when it determines
+ that more raw IFR bytes should be emitted to the output stream.
+ Here we just queue them up into an output buffer.
+
+Arguments:
+ ByteVal - the raw byte to emit to the output IFR stream
+ KeyByte - a value that can be used for debug.
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // Check for buffer overflow
+ //
+ if (mQueuedByteCount >= MAX_QUEUE_COUNT) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");
+ } else {
+ mQueuedBytes[mQueuedByteCount] = ByteVal;
+ mQueuedKeyBytes[mQueuedByteCount] = KeyByte;
+ mQueuedByteCount++;
+ }
+}
+
+int
+VfrOpcodeHandler::FlushQueue (
+ )
+/*++
+
+Routine Description:
+ This function is invoked to flush the internal IFR buffer.
+
+Arguments:
+ None
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+ UINT32 EmitNoneOnePair;
+
+ EmitNoneOnePair = 0;
+ //
+ // If the secondary varstore was specified, then we have to emit
+ // a varstore-select-pair opcode, which only applies to the following
+ // statement.
+ //
+ if (mSecondaryVarStoreIdSet) {
+ mSecondaryVarStoreIdSet = 0;
+ //
+ // If primary and secondary are the same as the current default
+ // varstore, then we don't have to do anything.
+ // Note that the varstore-select-pair only applies to the following
+ // opcode.
+ //
+ if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {
+ IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);
+ }
+ } else if (mPrimaryVarStoreIdSet != 0) {
+ mPrimaryVarStoreIdSet = 0;
+ if (mDefaultVarStoreId != mPrimaryVarStoreId) {
+ //
+ // The VFR statement referenced a different variable store
+ // than the last one we reported. Insert a new varstore select
+ // statement.
+ //
+ IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ mDefaultVarStoreId = mPrimaryVarStoreId;
+ }
+ }
+ //
+ // Likely a new opcode is being added. Since each opcode item in the IFR has
+ // a header that specifies the size of the opcode item (which we don't
+ // know until we find the next opcode in the VFR), we queue up bytes
+ // until we know the size. Then we write them out. So flush the queue
+ // now.
+ //
+ if (mQueuedOpcodeByteValid != 0) {
+ //
+ // Add the previous opcode byte, the length byte, and the binary
+ // data.
+ //
+ IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);
+ for (Count = 0; Count < mQueuedByteCount; Count++) {
+ IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);
+ }
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ }
+ return 0;
+}
+
+int
+VfrOpcodeHandler::IAddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This internal function is used to add actual IFR bytes to
+ the output stream. Most other functions queue up the bytes
+ in an internal buffer. Once they come here, there's no
+ going back.
+
+
+Arguments:
+ ByteVal - value to write to output
+ KeyByte - key value tied to the byte -- useful for debug
+ LineNum - line number from source file the byte resulted from
+
+Returns:
+ 0 - if successful
+ 1 - failed due to memory allocation failure
+
+--*/
+{
+ IFR_BYTE *NewByte;
+ NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));
+ if (NewByte == NULL) {
+ return 1;
+ }
+ memset ((char *)NewByte, 0, sizeof (IFR_BYTE));
+ NewByte->OpcodeByte = ByteVal;
+ NewByte->KeyByte = KeyByte;
+ NewByte->LineNum = LineNum;
+ //
+ // Add to the list
+ //
+ if (mIfrBytes == NULL) {
+ mIfrBytes = NewByte;
+ } else {
+ mLastIfrByte->Next = NewByte;
+ }
+ mLastIfrByte = NewByte;
+ mBytesWritten++;
+ return 0;
+}
+
+VOID
+WriteStandardFileHeader (
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+ This function is invoked to emit a standard header to an
+ output text file.
+
+Arguments:
+ OutFptr - file to write the header to
+
+Returns:
+ None
+
+--*/
+{
+ UINT32 TempIndex;
+ for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
+ fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
+ }
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+}