Removing C Pre-Processing from VfrCompile Tool. Now the input file for VfrCompile tool should be *.i file which was preprocessed by compiler. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1964 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			759 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			759 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2004 - 2005, 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 <Common/UefiBaseTypes.h>
 | 
						|
#include <Common/MultiPhase.h>
 | 
						|
#include <Common/InternalFormRepresentation.h>
 | 
						|
#include <Protocol/UgaDraw.h>  // for EFI_UGA_PIXEL definition
 | 
						|
#include <Protocol/Hii.h>
 | 
						|
 | 
						|
#include "EfiUtilityMsgs.h"
 | 
						|
#include "EfiVfr.h"
 | 
						|
#include "VfrServices.h"
 | 
						|
 | 
						|
 | 
						|
static const char *mSourceFileHeader[] = {
 | 
						|
  "//",
 | 
						|
  "//  DO NOT EDIT -- auto-generated file",
 | 
						|
  "//",
 | 
						|
  "//  This file is generated by the VFR compiler.",
 | 
						|
  "//",
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
typedef struct {
 | 
						|
   CHAR8    *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_CHECKBOX",                   sizeof (EFI_IFR_CHECKBOX) }, 
 | 
						|
  { "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_EXPR",                   sizeof (EFI_IFR_END_EXPR) }, 
 | 
						|
  { "EFI_IFR_GRAY_OUT",                   sizeof (EFI_IFR_GRAY_OUT) }, 
 | 
						|
  { "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;
 | 
						|
  CHAR8                     Line[MAX_LINE_LEN];
 | 
						|
  CHAR8                     *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.VfrFileName, "r")) == NULL) {
 | 
						|
      Warning (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "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");
 | 
						|
}
 |