mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-03 21:17:23 +01:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=764 Cc: Eric Dong <eric.dong@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			2475 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2475 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/** @file
 | 
						|
  
 | 
						|
  The definition of CFormPkg's member function
 | 
						|
 | 
						|
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
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.             
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "stdio.h"
 | 
						|
#include "assert.h"
 | 
						|
#include "VfrFormPkg.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * The definition of CFormPkg's member function
 | 
						|
 */
 | 
						|
 | 
						|
SPendingAssign::SPendingAssign (
 | 
						|
  IN CHAR8  *Key, 
 | 
						|
  IN VOID   *Addr, 
 | 
						|
  IN UINT32 Len, 
 | 
						|
  IN UINT32 LineNo,
 | 
						|
  IN CONST CHAR8  *Msg
 | 
						|
  )
 | 
						|
{
 | 
						|
  mKey    = NULL;
 | 
						|
  mAddr   = Addr;
 | 
						|
  mLen    = Len;
 | 
						|
  mFlag   = PENDING;
 | 
						|
  mLineNo = LineNo;
 | 
						|
  mMsg    = NULL;
 | 
						|
  mNext   = NULL;
 | 
						|
  if (Key != NULL) {
 | 
						|
    mKey = new CHAR8[strlen (Key) + 1];
 | 
						|
    if (mKey != NULL) {
 | 
						|
      strcpy (mKey, Key);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Msg != NULL) {
 | 
						|
    mMsg = new CHAR8[strlen (Msg) + 1];
 | 
						|
    if (mMsg != NULL) {
 | 
						|
      strcpy (mMsg, Msg);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
SPendingAssign::~SPendingAssign (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (mKey != NULL) {
 | 
						|
    delete[] mKey;
 | 
						|
  }
 | 
						|
  mAddr   = NULL;
 | 
						|
  mLen    = 0;
 | 
						|
  mLineNo = 0;
 | 
						|
  if (mMsg != NULL) {
 | 
						|
    delete[] mMsg;
 | 
						|
  }
 | 
						|
  mNext   = NULL;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
SPendingAssign::SetAddrAndLen (
 | 
						|
  IN VOID   *Addr, 
 | 
						|
  IN UINT32 LineNo
 | 
						|
  )
 | 
						|
{
 | 
						|
  mAddr   = Addr;
 | 
						|
  mLineNo = LineNo;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
SPendingAssign::AssignValue (
 | 
						|
  IN VOID   *Addr, 
 | 
						|
  IN UINT32 Len
 | 
						|
  )
 | 
						|
{
 | 
						|
  memmove (mAddr, Addr, (mLen < Len ? mLen : Len));
 | 
						|
  mFlag = ASSIGNED;
 | 
						|
}
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
SPendingAssign::GetKey (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mKey;
 | 
						|
}
 | 
						|
 | 
						|
CFormPkg::CFormPkg (
 | 
						|
  IN UINT32 BufferSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8       *BufferStart;
 | 
						|
  CHAR8       *BufferEnd;
 | 
						|
  SBufferNode *Node;
 | 
						|
 | 
						|
  mPkgLength           = 0;
 | 
						|
  mBufferSize          = 0;
 | 
						|
  mBufferNodeQueueHead = NULL;
 | 
						|
  mBufferNodeQueueTail = NULL;
 | 
						|
  mCurrBufferNode      = NULL;
 | 
						|
  mReadBufferNode      = NULL;
 | 
						|
  mReadBufferOffset    = 0;
 | 
						|
  PendingAssignList    = NULL;
 | 
						|
 | 
						|
  Node = new SBufferNode;
 | 
						|
  if (Node == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  BufferStart = new CHAR8[BufferSize];
 | 
						|
  if (BufferStart == NULL) {
 | 
						|
    delete Node;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  BufferEnd   = BufferStart + BufferSize;
 | 
						|
 | 
						|
  memset (BufferStart, 0, BufferSize);
 | 
						|
  Node->mBufferStart   = BufferStart;
 | 
						|
  Node->mBufferEnd     = BufferEnd;
 | 
						|
  Node->mBufferFree    = BufferStart;
 | 
						|
  Node->mNext          = NULL;
 | 
						|
 | 
						|
  mBufferSize          = BufferSize;
 | 
						|
  mBufferNodeQueueHead = Node;
 | 
						|
  mBufferNodeQueueTail = Node;
 | 
						|
  mCurrBufferNode      = Node;
 | 
						|
}
 | 
						|
 | 
						|
CFormPkg::~CFormPkg ()
 | 
						|
{
 | 
						|
  SBufferNode    *pBNode;
 | 
						|
  SPendingAssign *pPNode;
 | 
						|
 | 
						|
  while (mBufferNodeQueueHead != NULL) {
 | 
						|
    pBNode = mBufferNodeQueueHead;
 | 
						|
    mBufferNodeQueueHead = mBufferNodeQueueHead->mNext;
 | 
						|
    if (pBNode->mBufferStart != NULL) {
 | 
						|
      delete[] pBNode->mBufferStart;
 | 
						|
      delete pBNode;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  mBufferNodeQueueTail = NULL;
 | 
						|
  mCurrBufferNode      = NULL;
 | 
						|
 | 
						|
  while (PendingAssignList != NULL) {
 | 
						|
    pPNode = PendingAssignList;
 | 
						|
    PendingAssignList = PendingAssignList->mNext;
 | 
						|
    delete pPNode;
 | 
						|
  }
 | 
						|
  PendingAssignList = NULL;
 | 
						|
}
 | 
						|
 | 
						|
SBufferNode *
 | 
						|
CFormPkg::CreateNewNode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *Node;
 | 
						|
 | 
						|
  Node = new SBufferNode;
 | 
						|
  if (Node == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Node->mBufferStart = new CHAR8[mBufferSize];
 | 
						|
  if (Node->mBufferStart == NULL) {
 | 
						|
    delete Node;
 | 
						|
    return NULL;
 | 
						|
  } else {
 | 
						|
    memset (Node->mBufferStart, 0, mBufferSize);
 | 
						|
    Node->mBufferEnd  = Node->mBufferStart + mBufferSize;
 | 
						|
    Node->mBufferFree = Node->mBufferStart;
 | 
						|
    Node->mNext       = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return Node;
 | 
						|
}
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
CFormPkg::IfrBinBufferGet (
 | 
						|
  IN UINT32 Len
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8       *BinBuffer = NULL;
 | 
						|
  SBufferNode *Node      = NULL;
 | 
						|
 | 
						|
  if ((Len == 0) || (Len > mBufferSize)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) {
 | 
						|
    BinBuffer = mCurrBufferNode->mBufferFree;
 | 
						|
    mCurrBufferNode->mBufferFree += Len;
 | 
						|
  } else {
 | 
						|
    Node = CreateNewNode ();
 | 
						|
    if (Node == NULL) {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mBufferNodeQueueTail == NULL) {
 | 
						|
      mBufferNodeQueueHead = mBufferNodeQueueTail = Node;
 | 
						|
    } else {
 | 
						|
      mBufferNodeQueueTail->mNext = Node;
 | 
						|
      mBufferNodeQueueTail = Node;
 | 
						|
    }
 | 
						|
    mCurrBufferNode = Node;
 | 
						|
 | 
						|
    //
 | 
						|
    // Now try again.
 | 
						|
    //
 | 
						|
    BinBuffer = mCurrBufferNode->mBufferFree;
 | 
						|
    mCurrBufferNode->mBufferFree += Len;
 | 
						|
  }
 | 
						|
 | 
						|
  mPkgLength += Len;
 | 
						|
 | 
						|
  return BinBuffer;
 | 
						|
}
 | 
						|
 | 
						|
inline
 | 
						|
UINT32
 | 
						|
CFormPkg::GetPkgLength (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mPkgLength;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::Open (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mReadBufferNode   = mBufferNodeQueueHead;
 | 
						|
  mReadBufferOffset = 0;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::Close (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mReadBufferNode   = NULL;
 | 
						|
  mReadBufferOffset = 0;
 | 
						|
}
 | 
						|
 | 
						|
UINT32
 | 
						|
CFormPkg::Read (
 | 
						|
  IN CHAR8     *Buffer, 
 | 
						|
  IN UINT32    Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32       Index;
 | 
						|
 | 
						|
  if ((Size == 0) || (Buffer == NULL)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mReadBufferNode == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < Size; Index++) {
 | 
						|
    if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) {
 | 
						|
      Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];
 | 
						|
    } else {
 | 
						|
      if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) {
 | 
						|
        return Index;
 | 
						|
      } else {
 | 
						|
        mReadBufferOffset = 0;
 | 
						|
        Index --;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Size;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::BuildPkgHdr (
 | 
						|
  OUT EFI_HII_PACKAGE_HEADER **PkgHdr
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (PkgHdr == NULL) {
 | 
						|
    return VFR_RETURN_FATAL_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) {
 | 
						|
    return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM;
 | 
						|
  (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::BuildPkg (
 | 
						|
  OUT PACKAGE_DATA &TBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  
 | 
						|
  CHAR8  *Temp;
 | 
						|
  UINT32 Size;
 | 
						|
  CHAR8  Buffer[1024];
 | 
						|
 | 
						|
  if (TBuffer.Buffer != NULL) {
 | 
						|
    delete TBuffer.Buffer;
 | 
						|
  }
 | 
						|
 | 
						|
  TBuffer.Size = mPkgLength;
 | 
						|
  TBuffer.Buffer = NULL;
 | 
						|
  if (TBuffer.Size != 0) {
 | 
						|
    TBuffer.Buffer = new CHAR8[TBuffer.Size];
 | 
						|
  } else {
 | 
						|
    return VFR_RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Temp = TBuffer.Buffer;
 | 
						|
  Open ();
 | 
						|
  while ((Size = Read (Buffer, 1024)) != 0) {
 | 
						|
    memcpy (Temp, Buffer, Size);
 | 
						|
    Temp += Size;
 | 
						|
  }
 | 
						|
  Close ();
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::BuildPkg (
 | 
						|
  IN FILE  *Output,
 | 
						|
  IN PACKAGE_DATA *PkgData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_VFR_RETURN_CODE     Ret;
 | 
						|
  CHAR8                   Buffer[1024];
 | 
						|
  UINT32                  Size;
 | 
						|
  EFI_HII_PACKAGE_HEADER  *PkgHdr;
 | 
						|
 | 
						|
  if (Output == NULL) {
 | 
						|
    return VFR_RETURN_FATAL_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
 | 
						|
    return Ret;
 | 
						|
  }
 | 
						|
  fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);
 | 
						|
  delete PkgHdr;
 | 
						|
  
 | 
						|
  if (PkgData == NULL) {
 | 
						|
    Open ();
 | 
						|
    while ((Size = Read (Buffer, 1024)) != 0) {
 | 
						|
      fwrite (Buffer, Size, 1, Output);
 | 
						|
    }
 | 
						|
    Close ();
 | 
						|
  } else {
 | 
						|
    fwrite (PkgData->Buffer, PkgData->Size, 1, Output);
 | 
						|
  }
 | 
						|
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::_WRITE_PKG_LINE (
 | 
						|
  IN FILE         *pFile,
 | 
						|
  IN UINT32       LineBytes,
 | 
						|
  IN CONST CHAR8  *LineHeader,
 | 
						|
  IN CHAR8        *BlkBuf,
 | 
						|
  IN UINT32       BlkSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32    Index;
 | 
						|
 | 
						|
  if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < BlkSize; Index++) {
 | 
						|
    if ((Index % LineBytes) == 0) {
 | 
						|
      fprintf (pFile, "\n%s", LineHeader);
 | 
						|
    }
 | 
						|
    fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::_WRITE_PKG_END (
 | 
						|
  IN FILE         *pFile,
 | 
						|
  IN UINT32       LineBytes,
 | 
						|
  IN CONST CHAR8  *LineHeader,
 | 
						|
  IN CHAR8        *BlkBuf,
 | 
						|
  IN UINT32       BlkSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32    Index;
 | 
						|
 | 
						|
  if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < BlkSize - 1; Index++) {
 | 
						|
    if ((Index % LineBytes) == 0) {
 | 
						|
      fprintf (pFile, "\n%s", LineHeader);
 | 
						|
    }
 | 
						|
    fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Index % LineBytes) == 0) {
 | 
						|
    fprintf (pFile, "\n%s", LineHeader);
 | 
						|
  }
 | 
						|
  fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);
 | 
						|
}
 | 
						|
 | 
						|
#define BYTES_PRE_LINE 0x10
 | 
						|
UINT32   gAdjustOpcodeOffset = 0;
 | 
						|
BOOLEAN  gNeedAdjustOpcode   = FALSE;
 | 
						|
UINT32   gAdjustOpcodeLen    = 0;
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE 
 | 
						|
CFormPkg::GenCFile (
 | 
						|
  IN CHAR8 *BaseName,
 | 
						|
  IN FILE *pFile,
 | 
						|
  IN PACKAGE_DATA *PkgData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_VFR_RETURN_CODE          Ret;
 | 
						|
  CHAR8                        Buffer[BYTES_PRE_LINE * 8];
 | 
						|
  EFI_HII_PACKAGE_HEADER       *PkgHdr;
 | 
						|
  UINT32                       PkgLength  = 0;
 | 
						|
  UINT32                       ReadSize   = 0;
 | 
						|
 | 
						|
  if ((BaseName == NULL) || (pFile == NULL)) {
 | 
						|
    return VFR_RETURN_FATAL_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);
 | 
						|
 | 
						|
  if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
 | 
						|
    return Ret;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // For framework vfr file, the extension framework header will be added.
 | 
						|
  //
 | 
						|
  if (VfrCompatibleMode) {
 | 
						|
	  fprintf (pFile, "  // FRAMEWORK PACKAGE HEADER Length\n");
 | 
						|
	  PkgLength = PkgHdr->Length + sizeof (UINT32) + 2;
 | 
						|
	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));	
 | 
						|
	  fprintf (pFile, "\n\n  // FRAMEWORK PACKAGE HEADER Type\n");
 | 
						|
	  PkgLength = 3;
 | 
						|
	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT16));	
 | 
						|
	} else {
 | 
						|
	  fprintf (pFile, "  // ARRAY LENGTH\n");
 | 
						|
	  PkgLength = PkgHdr->Length + sizeof (UINT32);
 | 
						|
	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));	
 | 
						|
	}
 | 
						|
 | 
						|
  fprintf (pFile, "\n\n  // PACKAGE HEADER\n");
 | 
						|
  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));
 | 
						|
  PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
 | 
						|
  fprintf (pFile, "\n\n  // PACKAGE DATA\n");
 | 
						|
  
 | 
						|
  if (PkgData == NULL) {
 | 
						|
    Open ();
 | 
						|
    while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {
 | 
						|
      PkgLength += ReadSize;
 | 
						|
      if (PkgLength < PkgHdr->Length) {
 | 
						|
        _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
 | 
						|
      } else {
 | 
						|
        _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    Close ();
 | 
						|
  } else {
 | 
						|
    if (PkgData->Size % BYTES_PRE_LINE != 0) {
 | 
						|
      PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE);
 | 
						|
      _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
 | 
						|
      _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE);
 | 
						|
    } else {
 | 
						|
      PkgLength = PkgData->Size - BYTES_PRE_LINE;
 | 
						|
      _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
 | 
						|
      _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  delete PkgHdr;
 | 
						|
  fprintf (pFile, "\n};\n");
 | 
						|
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::AssignPending (
 | 
						|
  IN CHAR8  *Key, 
 | 
						|
  IN VOID   *ValAddr, 
 | 
						|
  IN UINT32 ValLen,
 | 
						|
  IN UINT32 LineNo,
 | 
						|
  IN CONST CHAR8  *Msg
 | 
						|
  )
 | 
						|
{
 | 
						|
  SPendingAssign *pNew;
 | 
						|
 | 
						|
  pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);
 | 
						|
  if (pNew == NULL) {
 | 
						|
    return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  pNew->mNext       = PendingAssignList;
 | 
						|
  PendingAssignList = pNew;
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::DoPendingAssign (
 | 
						|
  IN CHAR8  *Key, 
 | 
						|
  IN VOID   *ValAddr, 
 | 
						|
  IN UINT32 ValLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  SPendingAssign *pNode;
 | 
						|
 | 
						|
  if ((Key == NULL) || (ValAddr == NULL)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (strcmp (pNode->mKey, Key) == 0) {
 | 
						|
      pNode->AssignValue (ValAddr, ValLen);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
CFormPkg::HavePendingUnassigned (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SPendingAssign *pNode;
 | 
						|
 | 
						|
  for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mFlag == PENDING) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CFormPkg::PendingAssignPrintAll (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SPendingAssign *pNode;
 | 
						|
 | 
						|
  for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mFlag == PENDING) {
 | 
						|
      gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
SBufferNode *
 | 
						|
CFormPkg::GetBinBufferNodeForAddr (
 | 
						|
  IN CHAR8              *BinBuffAddr
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *TmpNode;
 | 
						|
 | 
						|
  TmpNode = mBufferNodeQueueHead;
 | 
						|
 | 
						|
  while (TmpNode != NULL) {
 | 
						|
    if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) {
 | 
						|
      return TmpNode;
 | 
						|
    }
 | 
						|
 | 
						|
    TmpNode = TmpNode->mNext;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
SBufferNode *
 | 
						|
CFormPkg::GetNodeBefore(
 | 
						|
  IN SBufferNode *CurrentNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *FirstNode   = mBufferNodeQueueHead;
 | 
						|
  SBufferNode *LastNode    = mBufferNodeQueueHead;
 | 
						|
 | 
						|
  while (FirstNode != NULL) {
 | 
						|
    if (FirstNode == CurrentNode) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    LastNode    = FirstNode;
 | 
						|
    FirstNode   = FirstNode->mNext;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FirstNode == NULL) {
 | 
						|
    LastNode = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return LastNode;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::InsertNodeBefore(
 | 
						|
  IN SBufferNode *CurrentNode,
 | 
						|
  IN SBufferNode *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *LastNode = GetNodeBefore (CurrentNode);
 | 
						|
 | 
						|
  if (LastNode == NULL) {
 | 
						|
    return VFR_RETURN_MISMATCHED;
 | 
						|
  }
 | 
						|
 | 
						|
  NewNode->mNext = LastNode->mNext;
 | 
						|
  LastNode->mNext = NewNode;
 | 
						|
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
CFormPkg::GetBufAddrBaseOnOffset (
 | 
						|
  IN UINT32      Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *TmpNode;
 | 
						|
  UINT32      TotalBufLen;
 | 
						|
  UINT32      CurrentBufLen;
 | 
						|
 | 
						|
  TotalBufLen = 0;
 | 
						|
 | 
						|
  for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) {
 | 
						|
    CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart;
 | 
						|
    if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) {
 | 
						|
      return TmpNode->mBufferStart + (Offset - TotalBufLen);
 | 
						|
    }
 | 
						|
 | 
						|
    TotalBufLen += CurrentBufLen;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::AdjustDynamicInsertOpcode (
 | 
						|
  IN CHAR8              *InserPositionAddr,
 | 
						|
  IN CHAR8              *InsertOpcodeAddr,
 | 
						|
  IN BOOLEAN            CreateOpcodeAfterParsingVfr
 | 
						|
  )
 | 
						|
{
 | 
						|
  SBufferNode *InserPositionNode;
 | 
						|
  SBufferNode *InsertOpcodeNode;
 | 
						|
  SBufferNode *NewRestoreNodeBegin;
 | 
						|
  SBufferNode *NewRestoreNodeEnd;
 | 
						|
  SBufferNode *NewLastEndNode;
 | 
						|
  SBufferNode *TmpNode;
 | 
						|
  UINT32      NeedRestoreCodeLen;
 | 
						|
 | 
						|
  NewRestoreNodeEnd = NULL;
 | 
						|
 | 
						|
  InserPositionNode  = GetBinBufferNodeForAddr(InserPositionAddr);
 | 
						|
  InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);
 | 
						|
  assert (InserPositionNode != NULL);
 | 
						|
  assert (InsertOpcodeNode  != NULL);
 | 
						|
 | 
						|
  if (InserPositionNode == InsertOpcodeNode) {
 | 
						|
    //
 | 
						|
    // Create New Node to save the restore opcode.
 | 
						|
    //
 | 
						|
    NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;
 | 
						|
    gAdjustOpcodeLen   = NeedRestoreCodeLen;
 | 
						|
    NewRestoreNodeBegin = CreateNewNode ();
 | 
						|
    if (NewRestoreNodeBegin == NULL) {
 | 
						|
      return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
    }
 | 
						|
    memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
 | 
						|
    NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
 | 
						|
 | 
						|
    //
 | 
						|
    // Override the restore buffer data.
 | 
						|
    //
 | 
						|
    memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
 | 
						|
    InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;
 | 
						|
    memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Create New Node to save the restore opcode.
 | 
						|
    //
 | 
						|
    NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;
 | 
						|
    gAdjustOpcodeLen   = NeedRestoreCodeLen;
 | 
						|
    NewRestoreNodeBegin = CreateNewNode ();
 | 
						|
    if (NewRestoreNodeBegin == NULL) {
 | 
						|
      return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
    }
 | 
						|
    memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
 | 
						|
    NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
 | 
						|
    //
 | 
						|
    // Override the restore buffer data.
 | 
						|
    //
 | 
						|
    InserPositionNode->mBufferFree -= NeedRestoreCodeLen;
 | 
						|
    //
 | 
						|
    // Link the restore data to new node.
 | 
						|
    //
 | 
						|
    NewRestoreNodeBegin->mNext = InserPositionNode->mNext;
 | 
						|
 | 
						|
    //
 | 
						|
    // Count the Adjust opcode len.
 | 
						|
    //
 | 
						|
    TmpNode = InserPositionNode->mNext;
 | 
						|
    while (TmpNode != InsertOpcodeNode) {
 | 
						|
      gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;
 | 
						|
      TmpNode = TmpNode->mNext;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Create New Node to save the last node of restore opcode.
 | 
						|
    //
 | 
						|
    NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
 | 
						|
    gAdjustOpcodeLen  += NeedRestoreCodeLen;
 | 
						|
    if (NeedRestoreCodeLen > 0) {
 | 
						|
      NewRestoreNodeEnd = CreateNewNode ();
 | 
						|
      if (NewRestoreNodeEnd == NULL) {
 | 
						|
        return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
      }
 | 
						|
      memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen);
 | 
						|
      NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen;
 | 
						|
      //
 | 
						|
      // Override the restore buffer data.
 | 
						|
      //
 | 
						|
      memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
 | 
						|
      InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
 | 
						|
 | 
						|
      //
 | 
						|
      // Insert the last restore data node.
 | 
						|
      //
 | 
						|
      TmpNode = GetNodeBefore (InsertOpcodeNode);
 | 
						|
      assert (TmpNode != NULL);
 | 
						|
 | 
						|
      if (TmpNode == InserPositionNode) {
 | 
						|
        NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;
 | 
						|
      } else {
 | 
						|
        TmpNode->mNext = NewRestoreNodeEnd;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Connect the dynamic opcode node to the node after InserPositionNode.
 | 
						|
      //
 | 
						|
      InserPositionNode->mNext = InsertOpcodeNode;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (CreateOpcodeAfterParsingVfr) {
 | 
						|
    //
 | 
						|
    // Th new opcodes were created after Parsing Vfr file,
 | 
						|
    // so the content in mBufferNodeQueueTail must be the new created opcodes.
 | 
						|
    // So connet the  NewRestoreNodeBegin to the tail and update the tail node.
 | 
						|
    //
 | 
						|
    mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
 | 
						|
    if (NewRestoreNodeEnd != NULL) {
 | 
						|
      mBufferNodeQueueTail = NewRestoreNodeEnd;
 | 
						|
    } else {
 | 
						|
      mBufferNodeQueueTail = NewRestoreNodeBegin;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
 | 
						|
      //
 | 
						|
      // End form set opcode all in the mBufferNodeQueueTail node.
 | 
						|
      //
 | 
						|
      NewLastEndNode = CreateNewNode ();
 | 
						|
      if (NewLastEndNode == NULL) {
 | 
						|
        return VFR_RETURN_OUT_FOR_RESOURCES;
 | 
						|
      }
 | 
						|
      NewLastEndNode->mBufferStart[0] = 0x29;
 | 
						|
      NewLastEndNode->mBufferStart[1] = 0x02;
 | 
						|
      NewLastEndNode->mBufferFree += 2;
 | 
						|
 | 
						|
      mBufferNodeQueueTail->mBufferFree -= 2;
 | 
						|
 | 
						|
      mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
 | 
						|
      if (NewRestoreNodeEnd != NULL) {
 | 
						|
        NewRestoreNodeEnd->mNext = NewLastEndNode;
 | 
						|
      } else {
 | 
						|
        NewRestoreNodeBegin->mNext = NewLastEndNode;
 | 
						|
      }
 | 
						|
 | 
						|
      mBufferNodeQueueTail = NewLastEndNode;
 | 
						|
    } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
 | 
						|
      TmpNode = GetNodeBefore(mBufferNodeQueueTail);
 | 
						|
      assert (TmpNode != NULL);
 | 
						|
 | 
						|
      TmpNode->mNext = NewRestoreNodeBegin;
 | 
						|
      if (NewRestoreNodeEnd != NULL) {
 | 
						|
        NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
 | 
						|
      } else {
 | 
						|
        NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  mCurrBufferNode = mBufferNodeQueueTail;
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CFormPkg::DeclarePendingQuestion (
 | 
						|
  IN CVfrVarDataTypeDB   &lCVfrVarDataTypeDB,
 | 
						|
  IN CVfrDataStorage     &lCVfrDataStorage,
 | 
						|
  IN CVfrQuestionDB      &lCVfrQuestionDB,
 | 
						|
  IN EFI_GUID            *LocalFormSetGuid,
 | 
						|
  IN UINT32              LineNo,
 | 
						|
  OUT CHAR8              **InsertOpcodeAddr
 | 
						|
  )
 | 
						|
{
 | 
						|
  SPendingAssign *pNode;
 | 
						|
  CHAR8          *VarStr;
 | 
						|
  UINT32         ArrayIdx;
 | 
						|
  CHAR8          FName[MAX_NAME_LEN];
 | 
						|
  CHAR8          *SName;
 | 
						|
  CHAR8          *NewStr;
 | 
						|
  UINT32         ShrinkSize = 0;
 | 
						|
  EFI_VFR_RETURN_CODE  ReturnCode;
 | 
						|
  EFI_VFR_VARSTORE_TYPE VarStoreType  = EFI_VFR_VARSTORE_INVALID;
 | 
						|
  UINT8    LFlags;
 | 
						|
  UINT32   MaxValue;
 | 
						|
  CIfrGuid *GuidObj = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Declare all questions as Numeric in DisableIf True
 | 
						|
  //
 | 
						|
  // DisableIf
 | 
						|
  CIfrDisableIf DIObj;
 | 
						|
  DIObj.SetLineNo (LineNo);
 | 
						|
  *InsertOpcodeAddr = DIObj.GetObjBinAddr<CHAR8>();
 | 
						|
  
 | 
						|
  //TrueOpcode
 | 
						|
  CIfrTrue TObj (LineNo);
 | 
						|
 | 
						|
  // Declare Numeric qeustion for each undefined question.
 | 
						|
  for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mFlag == PENDING) {
 | 
						|
      EFI_VARSTORE_INFO Info; 
 | 
						|
      EFI_QUESTION_ID   QId   = EFI_QUESTION_ID_INVALID;
 | 
						|
      //
 | 
						|
      // Register this question, assume it is normal question, not date or time question
 | 
						|
      //
 | 
						|
      VarStr = pNode->mKey;
 | 
						|
      ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId);
 | 
						|
      if (ReturnCode != VFR_RETURN_SUCCESS) {
 | 
						|
        gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
 | 
						|
        return ReturnCode;
 | 
						|
      }
 | 
						|
 
 | 
						|
#ifdef VFREXP_DEBUG
 | 
						|
      printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId);
 | 
						|
#endif
 | 
						|
      //
 | 
						|
      // Get Question Info, framework vfr VarName == StructName
 | 
						|
      //
 | 
						|
      ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx);
 | 
						|
      if (ReturnCode != VFR_RETURN_SUCCESS) {
 | 
						|
        gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable");
 | 
						|
        return ReturnCode;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Get VarStoreType
 | 
						|
      //
 | 
						|
      ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId);
 | 
						|
      if (ReturnCode != VFR_RETURN_SUCCESS) {
 | 
						|
        gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");
 | 
						|
        return ReturnCode;
 | 
						|
      }
 | 
						|
      VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId); 
 | 
						|
 | 
						|
      if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) {
 | 
						|
        ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx);
 | 
						|
      } else {
 | 
						|
        if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
 | 
						|
          ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);
 | 
						|
        } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) {
 | 
						|
          VarStr = pNode->mKey;
 | 
						|
          //convert VarStr with store name to VarStr with structure name
 | 
						|
          ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName);
 | 
						|
          if (ReturnCode == VFR_RETURN_SUCCESS) {
 | 
						|
            NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1];
 | 
						|
            NewStr[0] = '\0';
 | 
						|
            strcpy (NewStr, SName);
 | 
						|
            strcat (NewStr, VarStr + strlen (FName));
 | 
						|
            ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar);
 | 
						|
            delete[] NewStr;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          ReturnCode = VFR_RETURN_UNSUPPORTED;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (ReturnCode != VFR_RETURN_SUCCESS) {
 | 
						|
        gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
 | 
						|
        return ReturnCode;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If the storage is bit fields, create Guid opcode to wrap the numeric opcode.
 | 
						|
      //
 | 
						|
      if (Info.mIsBitVar) {
 | 
						|
        GuidObj = new CIfrGuid(0);
 | 
						|
        GuidObj->SetGuid (&gEdkiiIfrBitVarGuid);
 | 
						|
        GuidObj->SetLineNo(LineNo);
 | 
						|
      }
 | 
						|
 | 
						|
      CIfrNumeric CNObj;
 | 
						|
      CNObj.SetLineNo (LineNo);
 | 
						|
      CNObj.SetPrompt (0x0);
 | 
						|
      CNObj.SetHelp (0x0);
 | 
						|
      CNObj.SetQuestionId (QId);
 | 
						|
      CNObj.SetVarStoreInfo (&Info);
 | 
						|
 | 
						|
      //
 | 
						|
      // Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question.
 | 
						|
      //
 | 
						|
      if (Info.mIsBitVar) {
 | 
						|
        MaxValue = (1 << Info.mVarTotalSize) -1;
 | 
						|
        CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0);
 | 
						|
        ShrinkSize = 12;
 | 
						|
        LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize);
 | 
						|
        CNObj.SetFlagsForBitField (0, LFlags);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Numeric doesn't support BOOLEAN data type.
 | 
						|
        // BOOLEAN type has the same data size to UINT8.
 | 
						|
        //
 | 
						|
        if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
 | 
						|
          Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
 | 
						|
        }
 | 
						|
        CNObj.SetFlags (0, Info.mVarType);
 | 
						|
        //
 | 
						|
        // Use maximum value not to limit the vaild value for the undefined question.
 | 
						|
        //
 | 
						|
        switch (Info.mVarType) {
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_64:
 | 
						|
          CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
 | 
						|
          ShrinkSize = 0;
 | 
						|
          break;
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_32:
 | 
						|
          CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
 | 
						|
          ShrinkSize = 12;
 | 
						|
          break;
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_16:
 | 
						|
          CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
 | 
						|
          ShrinkSize = 18;
 | 
						|
          break;
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_8:
 | 
						|
          CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
 | 
						|
          ShrinkSize = 21;
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      CNObj.ShrinkBinSize (ShrinkSize);
 | 
						|
 | 
						|
      //
 | 
						|
      // For undefined Efi VarStore type question
 | 
						|
      // Append the extended guided opcode to contain VarName
 | 
						|
      //
 | 
						|
      if (VarStoreType == EFI_VFR_VARSTORE_EFI || VfrCompatibleMode) {
 | 
						|
        CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName);
 | 
						|
        CVNObj.SetLineNo (LineNo);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // End for Numeric
 | 
						|
      //
 | 
						|
      CIfrEnd CEObj;
 | 
						|
      CEObj.SetLineNo (LineNo);
 | 
						|
      //
 | 
						|
      // End for Guided opcode
 | 
						|
      //
 | 
						|
      if (GuidObj != NULL) {
 | 
						|
        CIfrEnd CEObjGuid;
 | 
						|
        CEObjGuid.SetLineNo (LineNo);
 | 
						|
        GuidObj->SetScope(1);
 | 
						|
        delete GuidObj;
 | 
						|
        GuidObj = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // End for DisableIf
 | 
						|
  //
 | 
						|
  CIfrEnd SEObj;
 | 
						|
  SEObj.SetLineNo (LineNo);
 | 
						|
 | 
						|
  return VFR_RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
CFormPkg gCFormPkg;
 | 
						|
 | 
						|
SIfrRecord::SIfrRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mIfrBinBuf = NULL;
 | 
						|
  mBinBufLen = 0;
 | 
						|
  mLineNo    = 0xFFFFFFFF;
 | 
						|
  mOffset    = 0xFFFFFFFF;
 | 
						|
  mNext      = NULL;
 | 
						|
}
 | 
						|
 | 
						|
SIfrRecord::~SIfrRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (mIfrBinBuf != NULL) {
 | 
						|
    //delete mIfrBinBuf;
 | 
						|
    mIfrBinBuf = NULL;
 | 
						|
  }
 | 
						|
  mLineNo      = 0xFFFFFFFF;
 | 
						|
  mOffset      = 0xFFFFFFFF;
 | 
						|
  mBinBufLen   = 0;
 | 
						|
  mNext        = NULL;
 | 
						|
}
 | 
						|
 | 
						|
CIfrRecordInfoDB::CIfrRecordInfoDB (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mSwitch            = TRUE;
 | 
						|
  mRecordCount       = EFI_IFR_RECORDINFO_IDX_START;
 | 
						|
  mIfrRecordListHead = NULL;
 | 
						|
  mIfrRecordListTail = NULL;
 | 
						|
  mAllDefaultTypeCount = 0;
 | 
						|
  for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) {
 | 
						|
    mAllDefaultIdArray[i] = 0xffff;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
CIfrRecordInfoDB::~CIfrRecordInfoDB (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNode;
 | 
						|
 | 
						|
  while (mIfrRecordListHead != NULL) {
 | 
						|
    pNode = mIfrRecordListHead;
 | 
						|
    mIfrRecordListHead = mIfrRecordListHead->mNext;
 | 
						|
    delete pNode;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
SIfrRecord *
 | 
						|
CIfrRecordInfoDB::GetRecordInfoFromIdx (
 | 
						|
  IN UINT32 RecordIdx
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32     Idx;
 | 
						|
  SIfrRecord *pNode = NULL;
 | 
						|
 | 
						|
  if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead;
 | 
						|
       (Idx != RecordIdx) && (pNode != NULL);
 | 
						|
       Idx++, pNode = pNode->mNext)
 | 
						|
  ;
 | 
						|
 | 
						|
  return pNode;
 | 
						|
}
 | 
						|
 | 
						|
UINT32
 | 
						|
CIfrRecordInfoDB::IfrRecordRegister (
 | 
						|
  IN UINT32 LineNo,
 | 
						|
  IN CHAR8  *IfrBinBuf,
 | 
						|
  IN UINT8  BinBufLen,
 | 
						|
  IN UINT32 Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNew;
 | 
						|
 | 
						|
  if (mSwitch == FALSE) {
 | 
						|
    return EFI_IFR_RECORDINFO_IDX_INVALUD;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((pNew = new SIfrRecord) == NULL) {
 | 
						|
    return EFI_IFR_RECORDINFO_IDX_INVALUD;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mIfrRecordListHead == NULL) {
 | 
						|
    mIfrRecordListHead = pNew;
 | 
						|
    mIfrRecordListTail = pNew;
 | 
						|
  } else {
 | 
						|
    mIfrRecordListTail->mNext = pNew;
 | 
						|
    mIfrRecordListTail = pNew;
 | 
						|
  }
 | 
						|
  mRecordCount++;
 | 
						|
 | 
						|
  return mRecordCount;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrRecordInfoUpdate (
 | 
						|
  IN UINT32 RecordIdx,
 | 
						|
  IN UINT32 LineNo,
 | 
						|
  IN CHAR8  *BinBuf,
 | 
						|
  IN UINT8  BinBufLen,
 | 
						|
  IN UINT32 Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNode;
 | 
						|
  SIfrRecord *Prev;
 | 
						|
 | 
						|
  if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (LineNo == 0) {
 | 
						|
    //
 | 
						|
    // Line number is not specified explicitly, try to use line number of previous opcode
 | 
						|
    //
 | 
						|
    Prev = GetRecordInfoFromIdx (RecordIdx - 1);
 | 
						|
    if (Prev != NULL) {
 | 
						|
      LineNo = Prev->mLineNo;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  pNode->mLineNo    = LineNo;
 | 
						|
  pNode->mOffset    = Offset;
 | 
						|
  pNode->mBinBufLen = BinBufLen;
 | 
						|
  pNode->mIfrBinBuf = BinBuf;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrRecordOutput (
 | 
						|
  OUT PACKAGE_DATA &TBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8      *Temp;
 | 
						|
  SIfrRecord *pNode; 
 | 
						|
 | 
						|
  if (TBuffer.Buffer != NULL) {
 | 
						|
    delete[] TBuffer.Buffer;
 | 
						|
  }
 | 
						|
 | 
						|
  TBuffer.Size = 0;
 | 
						|
  TBuffer.Buffer = NULL;
 | 
						|
 | 
						|
 | 
						|
  if (mSwitch == FALSE) {
 | 
						|
    return;
 | 
						|
  } 
 | 
						|
   
 | 
						|
  for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    TBuffer.Size += pNode->mBinBufLen;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (TBuffer.Size != 0) {
 | 
						|
    TBuffer.Buffer = new CHAR8[TBuffer.Size];
 | 
						|
  } else {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  
 | 
						|
  Temp = TBuffer.Buffer;
 | 
						|
 | 
						|
  for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mIfrBinBuf != NULL) {
 | 
						|
      memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen);
 | 
						|
      Temp += pNode->mBinBufLen;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return;   
 | 
						|
}   
 | 
						|
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrRecordOutput (
 | 
						|
  IN FILE   *File,
 | 
						|
  IN UINT32 LineNo
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNode;
 | 
						|
  UINT8      Index;
 | 
						|
  UINT32     TotalSize;
 | 
						|
 | 
						|
  if (mSwitch == FALSE) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (File == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  TotalSize = 0;
 | 
						|
 | 
						|
  for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mLineNo == LineNo || LineNo == 0) {
 | 
						|
      fprintf (File, ">%08X: ", pNode->mOffset);
 | 
						|
      TotalSize += pNode->mBinBufLen;
 | 
						|
      if (pNode->mIfrBinBuf != NULL) {
 | 
						|
        for (Index = 0; Index < pNode->mBinBufLen; Index++) {
 | 
						|
          fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));
 | 
						|
        }
 | 
						|
      }
 | 
						|
      fprintf (File, "\n");
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (LineNo == 0) {
 | 
						|
    fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// for framework vfr file
 | 
						|
// adjust opcode sequence for uefi IFR format
 | 
						|
// adjust inconsistent and varstore into the right position.
 | 
						|
//
 | 
						|
BOOLEAN
 | 
						|
CIfrRecordInfoDB::CheckQuestionOpCode (
 | 
						|
  IN UINT8 OpCode
 | 
						|
  )
 | 
						|
{
 | 
						|
  switch (OpCode) {
 | 
						|
  case EFI_IFR_CHECKBOX_OP:
 | 
						|
  case EFI_IFR_NUMERIC_OP:
 | 
						|
  case EFI_IFR_PASSWORD_OP:
 | 
						|
  case EFI_IFR_ONE_OF_OP:
 | 
						|
  case EFI_IFR_ACTION_OP:
 | 
						|
  case EFI_IFR_STRING_OP:
 | 
						|
  case EFI_IFR_DATE_OP:
 | 
						|
  case EFI_IFR_TIME_OP:
 | 
						|
  case EFI_IFR_ORDERED_LIST_OP:
 | 
						|
  case EFI_IFR_REF_OP:
 | 
						|
    return TRUE;
 | 
						|
  default:
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
CIfrRecordInfoDB::CheckIdOpCode (
 | 
						|
  IN UINT8 OpCode
 | 
						|
  )
 | 
						|
{
 | 
						|
  switch (OpCode) {
 | 
						|
  case EFI_IFR_EQ_ID_VAL_OP:
 | 
						|
  case EFI_IFR_EQ_ID_ID_OP:
 | 
						|
  case EFI_IFR_EQ_ID_VAL_LIST_OP:
 | 
						|
  case EFI_IFR_QUESTION_REF1_OP:
 | 
						|
    return TRUE;
 | 
						|
  default:
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
} 
 | 
						|
 | 
						|
EFI_QUESTION_ID
 | 
						|
CIfrRecordInfoDB::GetOpcodeQuestionId (
 | 
						|
  IN EFI_IFR_OP_HEADER *OpHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IFR_QUESTION_HEADER *QuestionHead;
 | 
						|
  
 | 
						|
  QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1);
 | 
						|
  
 | 
						|
  return QuestionHead->QuestionId;
 | 
						|
}
 | 
						|
 | 
						|
SIfrRecord *
 | 
						|
CIfrRecordInfoDB::GetRecordInfoFromOffset (
 | 
						|
  IN UINT32 Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNode = NULL;
 | 
						|
 | 
						|
  for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    if (pNode->mOffset == Offset) {
 | 
						|
      return pNode;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return pNode;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add just the op code position.
 | 
						|
 | 
						|
  Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,
 | 
						|
  so pDynamicOpcodeNodes is before mIfrRecordListTail.
 | 
						|
 | 
						|
  From
 | 
						|
 | 
						|
  |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|
 | 
						|
 | 
						|
  To
 | 
						|
 | 
						|
  |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|
 | 
						|
 | 
						|
  Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,
 | 
						|
  so new records are appennded to the end of OriginalIfrRecordListTail.
 | 
						|
 | 
						|
  From
 | 
						|
 | 
						|
  |mIfrRecordListHead + ...+ pAdjustNode +  ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|
 | 
						|
 | 
						|
  To
 | 
						|
 | 
						|
  |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode +  ... + OriginalIfrRecordListTail|
 | 
						|
 | 
						|
 | 
						|
  @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (
 | 
						|
  IN BOOLEAN  CreateOpcodeAfterParsingVfr
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32             OpcodeOffset;
 | 
						|
  SIfrRecord         *pNode, *pPreNode;
 | 
						|
  SIfrRecord         *pAdjustNode, *pNodeBeforeAdjust;
 | 
						|
  SIfrRecord         *pNodeBeforeDynamic;
 | 
						|
 | 
						|
  pPreNode            = NULL;
 | 
						|
  pAdjustNode         = NULL;
 | 
						|
  pNodeBeforeDynamic  = NULL;
 | 
						|
  OpcodeOffset        = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,
 | 
						|
  // and the node before pDynamicOpcodeNode.
 | 
						|
  //
 | 
						|
  for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {
 | 
						|
    if (OpcodeOffset == gAdjustOpcodeOffset) {
 | 
						|
      pAdjustNode       = pNode;
 | 
						|
      pNodeBeforeAdjust = pPreNode;
 | 
						|
    } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {
 | 
						|
      pNodeBeforeDynamic = pPreNode;
 | 
						|
    }
 | 
						|
    if (pNode->mNext != NULL) {
 | 
						|
      pPreNode = pNode;
 | 
						|
    }
 | 
						|
    OpcodeOffset += pNode->mBinBufLen;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the nodes whether exist.
 | 
						|
  //
 | 
						|
  if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL || pNodeBeforeAdjust == NULL) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Adjust the node. pPreNode save the Node before mIfrRecordListTail
 | 
						|
  //
 | 
						|
  pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext;
 | 
						|
  if (CreateOpcodeAfterParsingVfr) {
 | 
						|
    //
 | 
						|
    // mIfrRecordListTail is the end of pDynamicNode (Case2).
 | 
						|
    //
 | 
						|
    mIfrRecordListTail->mNext = pAdjustNode;
 | 
						|
    mIfrRecordListTail = pNodeBeforeDynamic;
 | 
						|
    mIfrRecordListTail->mNext = NULL;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    //pPreNode is the end of pDynamicNode(Case1).
 | 
						|
    //
 | 
						|
    pPreNode->mNext = pAdjustNode;
 | 
						|
    pNodeBeforeDynamic->mNext = mIfrRecordListTail;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.
 | 
						|
 | 
						|
  @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (
 | 
						|
  IN BOOLEAN  CreateOpcodeAfterParsingVfr
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord          *pRecord;
 | 
						|
 | 
						|
  //
 | 
						|
  // Base on the original offset info to update the record list.
 | 
						|
  //
 | 
						|
  if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) {
 | 
						|
    gCVfrErrorHandle.PrintMsg (0, (CHAR8 *)"Error", (CHAR8 *)"Can not find the adjust offset in the record.");
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Base on the opcode binary length to recalculate the offset for each opcode.
 | 
						|
  //
 | 
						|
  IfrAdjustOffsetForRecord();
 | 
						|
 | 
						|
  //
 | 
						|
  // Base on the offset to find the binary address.
 | 
						|
  //
 | 
						|
  pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset);
 | 
						|
  while (pRecord != NULL) {
 | 
						|
    pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);
 | 
						|
    pRecord = pRecord->mNext;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrAdjustOffsetForRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32             OpcodeOffset;
 | 
						|
  SIfrRecord         *pNode;
 | 
						|
 | 
						|
  OpcodeOffset = 0;
 | 
						|
  for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
 | 
						|
    pNode->mOffset = OpcodeOffset;
 | 
						|
    OpcodeOffset += pNode->mBinBufLen;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_VFR_RETURN_CODE
 | 
						|
CIfrRecordInfoDB::IfrRecordAdjust (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord *pNode, *preNode;
 | 
						|
  SIfrRecord *uNode, *tNode;
 | 
						|
  EFI_IFR_OP_HEADER  *OpHead, *tOpHead;
 | 
						|
  EFI_QUESTION_ID    QuestionId;
 | 
						|
  UINT32             StackCount;
 | 
						|
  UINT32             QuestionScope;
 | 
						|
  CHAR8              ErrorMsg[MAX_STRING_LEN] = {0, };
 | 
						|
  EFI_VFR_RETURN_CODE  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Init local variable
 | 
						|
  //
 | 
						|
  Status = VFR_RETURN_SUCCESS;
 | 
						|
  pNode = mIfrRecordListHead;
 | 
						|
  preNode = pNode;
 | 
						|
  QuestionScope = 0;
 | 
						|
  while (pNode != NULL) {
 | 
						|
    OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
 | 
						|
    
 | 
						|
    //
 | 
						|
    // make sure the inconsistent opcode in question scope
 | 
						|
    //
 | 
						|
    if (QuestionScope > 0) {
 | 
						|
      QuestionScope += OpHead->Scope;
 | 
						|
      if (OpHead->OpCode == EFI_IFR_END_OP) {
 | 
						|
        QuestionScope --;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (CheckQuestionOpCode (OpHead->OpCode)) {
 | 
						|
      QuestionScope = 1;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // for the inconsistent opcode not in question scope, adjust it
 | 
						|
    //
 | 
						|
    if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) {
 | 
						|
      //
 | 
						|
      // for inconsistent opcode not in question scope
 | 
						|
      //
 | 
						|
 | 
						|
      //
 | 
						|
      // Count inconsistent opcode Scope 
 | 
						|
      //
 | 
						|
      StackCount = OpHead->Scope;
 | 
						|
      QuestionId = EFI_QUESTION_ID_INVALID;
 | 
						|
      tNode = pNode;
 | 
						|
      while (tNode != NULL && StackCount > 0) {
 | 
						|
        tNode = tNode->mNext;
 | 
						|
        tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf;
 | 
						|
        //
 | 
						|
        // Calculate Scope Number
 | 
						|
        //
 | 
						|
        StackCount += tOpHead->Scope;
 | 
						|
        if (tOpHead->OpCode == EFI_IFR_END_OP) {
 | 
						|
          StackCount --;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // by IdEqual opcode to get QuestionId
 | 
						|
        //
 | 
						|
        if (QuestionId == EFI_QUESTION_ID_INVALID && 
 | 
						|
            CheckIdOpCode (tOpHead->OpCode)) {
 | 
						|
          QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) {
 | 
						|
        //
 | 
						|
        // report error; not found
 | 
						|
        //
 | 
						|
        sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId);
 | 
						|
        gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
 | 
						|
        Status = VFR_RETURN_MISMATCHED;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // extract inconsistent opcode list
 | 
						|
      // pNode is Incosistent opcode, tNode is End Opcode
 | 
						|
      //
 | 
						|
      
 | 
						|
      //
 | 
						|
      // insert inconsistent opcode list into the right question scope by questionid
 | 
						|
      //
 | 
						|
      for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) {
 | 
						|
        tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf;
 | 
						|
        if (CheckQuestionOpCode (tOpHead->OpCode) && 
 | 
						|
            (QuestionId == GetOpcodeQuestionId (tOpHead))) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // insert inconsistent opcode list and check LATE_CHECK flag
 | 
						|
      //
 | 
						|
      if (uNode != NULL) {
 | 
						|
        if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) {
 | 
						|
          //
 | 
						|
          // if LATE_CHECK flag is set, change inconsistent to nosumbit
 | 
						|
          //
 | 
						|
          OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP;
 | 
						|
        }
 | 
						|
        
 | 
						|
        //
 | 
						|
        // skip the default storage for Date and Time
 | 
						|
        //
 | 
						|
        if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) {
 | 
						|
          uNode = uNode->mNext;
 | 
						|
        }
 | 
						|
 | 
						|
        preNode->mNext = tNode->mNext;
 | 
						|
        tNode->mNext = uNode->mNext;
 | 
						|
        uNode->mNext = pNode;
 | 
						|
        //
 | 
						|
        // reset pNode to head list, scan the whole list again.
 | 
						|
        //
 | 
						|
        pNode = mIfrRecordListHead;
 | 
						|
        preNode = pNode;
 | 
						|
        QuestionScope = 0;
 | 
						|
        continue;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // not found matched question id, report error
 | 
						|
        //
 | 
						|
        sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId);
 | 
						|
        gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
 | 
						|
        Status = VFR_RETURN_MISMATCHED;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP || 
 | 
						|
               OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) {
 | 
						|
      //
 | 
						|
      // for new added group of varstore opcode
 | 
						|
      //
 | 
						|
      tNode = pNode;
 | 
						|
      while (tNode->mNext != NULL) {
 | 
						|
        tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf;
 | 
						|
        if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP && 
 | 
						|
            tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) {
 | 
						|
          break;    
 | 
						|
        }
 | 
						|
        tNode = tNode->mNext;
 | 
						|
      }
 | 
						|
 | 
						|
      if (tNode->mNext == NULL) {
 | 
						|
        //
 | 
						|
        // invalid IfrCode, IfrCode end by EndOpCode
 | 
						|
        // 
 | 
						|
        gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end");
 | 
						|
        Status = VFR_RETURN_MISMATCHED;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      
 | 
						|
      if (tOpHead->OpCode != EFI_IFR_END_OP) {
 | 
						|
          //
 | 
						|
          // not new added varstore, which are not needed to be adjust.
 | 
						|
          //
 | 
						|
          preNode = tNode;
 | 
						|
          pNode   = tNode->mNext;
 | 
						|
          continue;        
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // move new added varstore opcode to the position befor form opcode 
 | 
						|
        // varstore opcode between pNode and tNode
 | 
						|
        //
 | 
						|
 | 
						|
        //
 | 
						|
        // search form opcode from begin
 | 
						|
        //
 | 
						|
        for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) {
 | 
						|
          tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf;
 | 
						|
          if (tOpHead->OpCode == EFI_IFR_FORM_OP) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Insert varstore opcode beform form opcode if form opcode is found
 | 
						|
        //
 | 
						|
        if (uNode->mNext != NULL) {
 | 
						|
          preNode->mNext = tNode->mNext;
 | 
						|
          tNode->mNext = uNode->mNext;
 | 
						|
          uNode->mNext = pNode;
 | 
						|
          //
 | 
						|
          // reset pNode to head list, scan the whole list again.
 | 
						|
          //
 | 
						|
          pNode = mIfrRecordListHead;
 | 
						|
          preNode = pNode;
 | 
						|
          QuestionScope = 0;
 | 
						|
          continue;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // not found form, continue scan IfrRecord list
 | 
						|
          //
 | 
						|
          preNode = tNode;
 | 
						|
          pNode   = tNode->mNext;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // next node
 | 
						|
    //
 | 
						|
    preNode = pNode;
 | 
						|
    pNode = pNode->mNext; 
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Update Ifr Opcode Offset
 | 
						|
  //
 | 
						|
  if (Status == VFR_RETURN_SUCCESS) {
 | 
						|
    IfrAdjustOffsetForRecord ();
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not
 | 
						|
  given by expression, should save the default info for the Buffer VarStore.
 | 
						|
 | 
						|
  @param  DefaultId           The default id.
 | 
						|
  @param  pQuestionNode       Point to the question opcode node.
 | 
						|
  @param  Value               The default value.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (
 | 
						|
  IN  UINT16                  DefaultId,
 | 
						|
  IN  SIfrRecord              *pQuestionNode,
 | 
						|
  IN  EFI_IFR_TYPE_VALUE      Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                   *VarStoreName = NULL;
 | 
						|
  EFI_VFR_VARSTORE_TYPE    VarStoreType  = EFI_VFR_VARSTORE_INVALID;
 | 
						|
  EFI_GUID                 *VarGuid      = NULL;
 | 
						|
  EFI_VARSTORE_INFO        VarInfo;
 | 
						|
  EFI_IFR_QUESTION_HEADER  *QuestionHead;
 | 
						|
  EFI_IFR_OP_HEADER        *pQuestionOpHead;
 | 
						|
 | 
						|
  pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
 | 
						|
  QuestionHead    = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Var Store name and type.
 | 
						|
  //
 | 
						|
  gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName);
 | 
						|
  VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId);
 | 
						|
  VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId);
 | 
						|
 | 
						|
  //
 | 
						|
  // Only for Buffer storage need to save the default info in the storage.
 | 
						|
  // Other type storage, just return.
 | 
						|
  //
 | 
						|
  if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) {
 | 
						|
    return;
 | 
						|
  } else {
 | 
						|
    VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset;
 | 
						|
    VarInfo.mVarStoreId = QuestionHead->VarStoreId;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the buffer storage info about this question.
 | 
						|
  //
 | 
						|
  gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo);
 | 
						|
 | 
						|
  //
 | 
						|
  // Add action.
 | 
						|
  //
 | 
						|
  gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
 | 
						|
    DefaultId,
 | 
						|
    VarInfo,
 | 
						|
    VarStoreName,
 | 
						|
    VarGuid,
 | 
						|
    VarInfo.mVarType,
 | 
						|
    Value
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Record the number and default id of all defaultstore opcode.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrGetDefaultStoreInfo (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord             *pNode;
 | 
						|
  EFI_IFR_OP_HEADER      *pOpHead;
 | 
						|
  EFI_IFR_DEFAULTSTORE   *DefaultStore;
 | 
						|
 | 
						|
  pNode                = mIfrRecordListHead;
 | 
						|
  mAllDefaultTypeCount = 0;
 | 
						|
 | 
						|
  while (pNode != NULL) {
 | 
						|
    pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
 | 
						|
 | 
						|
    if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){
 | 
						|
      DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf;
 | 
						|
      mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId;
 | 
						|
    }
 | 
						|
    pNode = pNode->mNext;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create new default opcode record.
 | 
						|
 | 
						|
  @param    Size            The new default opcode size.
 | 
						|
  @param    DefaultId       The new default id.
 | 
						|
  @param    Type            The new default type.
 | 
						|
  @param    LineNo          The line number of the new record.
 | 
						|
  @param    Value           The new default value.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrCreateDefaultRecord(
 | 
						|
  IN UINT8               Size,
 | 
						|
  IN UINT16              DefaultId,
 | 
						|
  IN UINT8               Type,
 | 
						|
  IN UINT32              LineNo,
 | 
						|
  IN EFI_IFR_TYPE_VALUE  Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  CIfrDefault   *DObj;
 | 
						|
  CIfrDefault2  *DObj2;
 | 
						|
 | 
						|
  DObj  = NULL;
 | 
						|
  DObj2 = NULL;
 | 
						|
 | 
						|
  if (Type == EFI_IFR_TYPE_OTHER) {
 | 
						|
    DObj2 = new CIfrDefault2 (Size);
 | 
						|
    DObj2->SetDefaultId(DefaultId);
 | 
						|
    DObj2->SetType(Type);
 | 
						|
    DObj2->SetLineNo(LineNo);
 | 
						|
    DObj2->SetScope (1);
 | 
						|
    delete DObj2;
 | 
						|
  } else {
 | 
						|
    DObj = new CIfrDefault (Size);
 | 
						|
    DObj->SetDefaultId(DefaultId);
 | 
						|
    DObj->SetType(Type);
 | 
						|
    DObj->SetLineNo(LineNo);
 | 
						|
    DObj->SetValue (Value);
 | 
						|
    delete DObj;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create new default opcode for question base on the QuestionDefaultInfo.
 | 
						|
 | 
						|
  @param  pQuestionNode              Point to the question opcode Node.
 | 
						|
  @param  QuestionDefaultInfo        Point to the QuestionDefaultInfo for current question.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrCreateDefaultForQuestion (
 | 
						|
  IN  SIfrRecord              *pQuestionNode,
 | 
						|
  IN  QuestionDefaultRecord   *QuestionDefaultInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IFR_OP_HEADER      *pOpHead;
 | 
						|
  EFI_IFR_DEFAULT        *Default;
 | 
						|
  SIfrRecord             *pSNode;
 | 
						|
  SIfrRecord             *pENode;
 | 
						|
  SIfrRecord             *pDefaultNode;
 | 
						|
  CIfrObj                *Obj;
 | 
						|
  CHAR8                  *ObjBinBuf;
 | 
						|
  UINT8                  ScopeCount;
 | 
						|
  UINT8                  OpcodeNumber;
 | 
						|
  UINT8                  OpcodeCount;
 | 
						|
  UINT8                  DefaultSize;
 | 
						|
  EFI_IFR_ONE_OF_OPTION  *DefaultOptionOpcode;
 | 
						|
  EFI_IFR_TYPE_VALUE     CheckBoxDefaultValue;
 | 
						|
 | 
						|
  CheckBoxDefaultValue.b = 1;
 | 
						|
  pOpHead                = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
 | 
						|
  ScopeCount             = 0;
 | 
						|
  OpcodeCount            = 0;
 | 
						|
  Obj                    = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
 | 
						|
  //
 | 
						|
  gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset;
 | 
						|
  //
 | 
						|
  // Case 1:
 | 
						|
  // For oneof, the default with smallest default id is given by the option flag.
 | 
						|
  // So create the missing defaults base on the oneof option value(mDefaultValueRecord).
 | 
						|
  //
 | 
						|
  if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
 | 
						|
    DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf;
 | 
						|
    DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value);
 | 
						|
    DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value);
 | 
						|
    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
        IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value);
 | 
						|
        //
 | 
						|
        // Save the new created default in the buffer storage.
 | 
						|
        //
 | 
						|
        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Case2:
 | 
						|
  // For checkbox, the default with smallest default id is given by the question flag.
 | 
						|
  // And create the missing defaults with true value.
 | 
						|
  //
 | 
						|
  if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
 | 
						|
    DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN);
 | 
						|
    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
        IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue);
 | 
						|
        //
 | 
						|
        // Save the new created default.
 | 
						|
        //
 | 
						|
        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Case3:
 | 
						|
  // The default with smallest default id is given by the default opcode.
 | 
						|
  // So create the missing defaults base on the value in the default opcode.
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.
 | 
						|
  //
 | 
						|
  pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord;
 | 
						|
  Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf;
 | 
						|
  //
 | 
						|
  // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
 | 
						|
  //
 | 
						|
  gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset;
 | 
						|
 | 
						|
  if (Default->Type == EFI_IFR_TYPE_OTHER) {
 | 
						|
    //
 | 
						|
    // EFI_IFR_DEFAULT_2 opcode.
 | 
						|
    //
 | 
						|
    // Point to the first expression opcode.
 | 
						|
    //
 | 
						|
    pSNode = pDefaultNode->mNext;
 | 
						|
    pENode = NULL;
 | 
						|
    ScopeCount++;
 | 
						|
    //
 | 
						|
    // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)
 | 
						|
    //
 | 
						|
    while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) {
 | 
						|
      pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
 | 
						|
      if (pOpHead->Scope == 1) {
 | 
						|
        ScopeCount++;
 | 
						|
      }
 | 
						|
      if (pOpHead->OpCode == EFI_IFR_END_OP) {
 | 
						|
        ScopeCount--;
 | 
						|
      }
 | 
						|
      pENode = pSNode;
 | 
						|
      pSNode = pSNode->mNext;
 | 
						|
      OpcodeCount++;
 | 
						|
    }
 | 
						|
 | 
						|
    assert (pSNode);
 | 
						|
    assert (pENode);
 | 
						|
 | 
						|
    //
 | 
						|
    // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
 | 
						|
    //
 | 
						|
    gAdjustOpcodeOffset = pSNode->mOffset;
 | 
						|
    //
 | 
						|
    // Create new default opcode node for missing default.
 | 
						|
    //
 | 
						|
    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
      OpcodeNumber = OpcodeCount;
 | 
						|
      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
        IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value);
 | 
						|
        //
 | 
						|
        // Point to the first expression opcode node.
 | 
						|
        //
 | 
						|
        pSNode = pDefaultNode->mNext;
 | 
						|
        //
 | 
						|
        // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.
 | 
						|
        //
 | 
						|
        while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) {
 | 
						|
          pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
 | 
						|
          Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);
 | 
						|
          assert (Obj != NULL);
 | 
						|
          Obj->SetLineNo (pSNode->mLineNo);
 | 
						|
          ObjBinBuf = Obj->GetObjBinAddr<CHAR8>();
 | 
						|
          memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);
 | 
						|
          delete Obj;
 | 
						|
          pSNode = pSNode->mNext;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // EFI_IFR_DEFAULT opcode.
 | 
						|
    //
 | 
						|
    // Create new default opcode node for missing default.
 | 
						|
    //
 | 
						|
    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
        IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value);
 | 
						|
        //
 | 
						|
        // Save the new created default in the buffer storage..
 | 
						|
        //
 | 
						|
        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Parse the default information in a question, get the QuestionDefaultInfo.
 | 
						|
 | 
						|
  @param  pQuestionNode          Point to the question record Node.
 | 
						|
  @param  QuestionDefaultInfo    On return, point to the QuestionDefaultInfo.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(
 | 
						|
  IN  SIfrRecord              *pQuestionNode,
 | 
						|
  OUT QuestionDefaultRecord   *QuestionDefaultInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord              *pSNode;
 | 
						|
  EFI_IFR_ONE_OF_OPTION   *OneofOptionOpcode;
 | 
						|
  EFI_IFR_OP_HEADER       *pSOpHead;
 | 
						|
  EFI_IFR_CHECKBOX        *CheckBoxOpcode;
 | 
						|
  EFI_IFR_DEFAULT         *DefaultOpcode;
 | 
						|
  BOOLEAN                 IsOneOfOpcode;
 | 
						|
  UINT16                  SmallestDefaultId;
 | 
						|
  UINT8                   ScopeCount;
 | 
						|
 | 
						|
  SmallestDefaultId  = 0xffff;
 | 
						|
  IsOneOfOpcode      = FALSE;
 | 
						|
  ScopeCount         = 0;
 | 
						|
  pSNode             = pQuestionNode;
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse all the opcodes in the Question.
 | 
						|
  //
 | 
						|
  while (pSNode != NULL) {
 | 
						|
    pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
 | 
						|
    //
 | 
						|
    // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.
 | 
						|
    // Scopes may be nested within other scopes.
 | 
						|
    // When finishing parsing a question, the scope count must be zero.
 | 
						|
    //
 | 
						|
    if (pSOpHead->Scope == 1) {
 | 
						|
      ScopeCount++;
 | 
						|
    }
 | 
						|
    if (pSOpHead->OpCode == EFI_IFR_END_OP) {
 | 
						|
      ScopeCount--;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check whether finishing parsing a question.
 | 
						|
    //
 | 
						|
    if (ScopeCount == 0) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Record the default information in the question.
 | 
						|
    //
 | 
						|
    switch (pSOpHead->OpCode) {
 | 
						|
    case EFI_IFR_ONE_OF_OP:
 | 
						|
      IsOneOfOpcode = TRUE;
 | 
						|
      break;
 | 
						|
    case EFI_IFR_CHECKBOX_OP:
 | 
						|
      //
 | 
						|
      // The default info of check box may be given by flag.
 | 
						|
      // So need to check the flag of check box.
 | 
						|
      //
 | 
						|
      CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf;
 | 
						|
      if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) {
 | 
						|
        //
 | 
						|
        // Check whether need to update the smallest default id.
 | 
						|
        //
 | 
						|
        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
 | 
						|
          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Update the QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
 | 
						|
            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
              QuestionDefaultInfo->mDefaultNumber ++;
 | 
						|
              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) {
 | 
						|
        //
 | 
						|
        // Check whether need to update the smallest default id.
 | 
						|
        //
 | 
						|
        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
 | 
						|
          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Update the QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
 | 
						|
            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
              QuestionDefaultInfo->mDefaultNumber ++;
 | 
						|
              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case EFI_IFR_ONE_OF_OPTION_OP:
 | 
						|
      if (!IsOneOfOpcode) {
 | 
						|
        //
 | 
						|
        // Only check the option in oneof.
 | 
						|
        //
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf;
 | 
						|
      if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
 | 
						|
        //
 | 
						|
        // The option is used as the standard default.
 | 
						|
        // Check whether need to update the smallest default id and QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
 | 
						|
          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
 | 
						|
          QuestionDefaultInfo->mDefaultValueRecord = pSNode;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Update the IsDefaultIdExist array in QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
 | 
						|
            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
              QuestionDefaultInfo->mDefaultNumber ++;
 | 
						|
              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) {
 | 
						|
        //
 | 
						|
        // This option is used as the manufacture default.
 | 
						|
        // Check whether need to update the smallest default id and QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
 | 
						|
          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
 | 
						|
          QuestionDefaultInfo->mDefaultValueRecord = pSNode;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Update the QuestionDefaultInfo.
 | 
						|
        //
 | 
						|
        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
 | 
						|
          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
 | 
						|
            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
              QuestionDefaultInfo->mDefaultNumber ++;
 | 
						|
              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case EFI_IFR_DEFAULT_OP:
 | 
						|
      DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf;
 | 
						|
      //
 | 
						|
      // Check whether need to update the smallest default id and QuestionDefaultInfo.
 | 
						|
      //
 | 
						|
      if (SmallestDefaultId >= DefaultOpcode->DefaultId ) {
 | 
						|
        SmallestDefaultId = DefaultOpcode->DefaultId;
 | 
						|
        QuestionDefaultInfo->mDefaultValueRecord= pSNode;
 | 
						|
        QuestionDefaultInfo->mIsDefaultOpcode= TRUE;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Update the QuestionDefaultInfo.
 | 
						|
      //
 | 
						|
      for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){
 | 
						|
        if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) {
 | 
						|
          if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
 | 
						|
            QuestionDefaultInfo->mDefaultNumber ++;
 | 
						|
            QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Parse next opcode in this question.
 | 
						|
    //
 | 
						|
    pSNode = pSNode->mNext;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check or add default for question if need.
 | 
						|
 | 
						|
  This function will check the default info for question.
 | 
						|
  If the question has default, but the default number < defaultstore opcode number.
 | 
						|
  will do following two action :
 | 
						|
 | 
						|
  1. if (AutoDefault) will add default for question to support all kinds of defaults.
 | 
						|
  2. if (CheckDefault) will generate an error to tell user the question misses some default value.
 | 
						|
 | 
						|
  We assume that the two options can not be TRUE at same time.
 | 
						|
  If they are TRUE at same time, only do the action corresponding to AutoDefault option.
 | 
						|
 | 
						|
  @param  AutoDefault          Add default for question if needed
 | 
						|
  @param  CheckDefault         Check the default info, if missing default, generates an error.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CIfrRecordInfoDB::IfrCheckAddDefaultRecord (
 | 
						|
  BOOLEAN  AutoDefault,
 | 
						|
  BOOLEAN  CheckDefault
 | 
						|
  )
 | 
						|
{
 | 
						|
  SIfrRecord            *pNode;
 | 
						|
  SIfrRecord            *pTailNode;
 | 
						|
  SIfrRecord            *pStartAdjustNode;
 | 
						|
  EFI_IFR_OP_HEADER     *pOpHead;
 | 
						|
  QuestionDefaultRecord  QuestionDefaultInfo;
 | 
						|
  UINT8                  MissingDefaultCount;
 | 
						|
  CHAR8                  Msg[MAX_STRING_LEN] = {0, };
 | 
						|
 | 
						|
  pNode               = mIfrRecordListHead;
 | 
						|
 | 
						|
  //
 | 
						|
  // Record the number and default id of all defaultstore opcode.
 | 
						|
  //
 | 
						|
  IfrGetDefaultStoreInfo ();
 | 
						|
 | 
						|
  while (pNode != NULL) {
 | 
						|
    pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
 | 
						|
    //
 | 
						|
    // Check whether is question opcode.
 | 
						|
    //
 | 
						|
    if (CheckQuestionOpCode (pOpHead->OpCode)) {
 | 
						|
      //
 | 
						|
      // Initialize some local variables here, because they vary with question.
 | 
						|
      // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.
 | 
						|
      //
 | 
						|
      memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord));
 | 
						|
      pTailNode = mIfrRecordListTail;
 | 
						|
      //
 | 
						|
      // Get the QuestionDefaultInfo for current question.
 | 
						|
      //
 | 
						|
      IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo);
 | 
						|
 | 
						|
      if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) {
 | 
						|
        if (AutoDefault) {
 | 
						|
          //
 | 
						|
          // Create default for question which misses default.
 | 
						|
          //
 | 
						|
          IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo);
 | 
						|
 | 
						|
          //
 | 
						|
          // Adjust the buffer content.
 | 
						|
          // pStartAdjustNode->mIfrBinBuf points to the insert position.
 | 
						|
          // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.
 | 
						|
          //
 | 
						|
          pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset);
 | 
						|
          gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE);
 | 
						|
 | 
						|
          //
 | 
						|
          // Update the record info.
 | 
						|
          //
 | 
						|
          IfrUpdateRecordInfoForDynamicOpcode (TRUE);
 | 
						|
        } else if (CheckDefault) {
 | 
						|
          //
 | 
						|
          // Generate an error for question which misses default.
 | 
						|
          //
 | 
						|
          MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber;
 | 
						|
          sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode);
 | 
						|
          gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // parse next opcode.
 | 
						|
    //
 | 
						|
    pNode = pNode->mNext;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
CIfrRecordInfoDB gCIfrRecordInfoDB;
 | 
						|
 | 
						|
VOID
 | 
						|
CIfrObj::_EMIT_PENDING_OBJ (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8  *ObjBinBuf = NULL;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // do nothing
 | 
						|
  //
 | 
						|
  if (!mDelayEmit || !gCreateOp) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mPkgOffset = gCFormPkg.GetPkgLength ();
 | 
						|
  //
 | 
						|
  // update data buffer to package data
 | 
						|
  //
 | 
						|
  ObjBinBuf  = gCFormPkg.IfrBinBufferGet (mObjBinLen);
 | 
						|
  if (ObjBinBuf != NULL) {
 | 
						|
    memmove (ObjBinBuf, mObjBinBuf, mObjBinLen);
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // update bin buffer to package data buffer
 | 
						|
  //
 | 
						|
  if (mObjBinBuf != NULL) {
 | 
						|
    delete[] mObjBinBuf;
 | 
						|
    mObjBinBuf = ObjBinBuf;
 | 
						|
  }
 | 
						|
  
 | 
						|
  mDelayEmit = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The definition of CIfrObj's member function
 | 
						|
 */
 | 
						|
static struct {
 | 
						|
  UINT8  mSize;
 | 
						|
  UINT8  mScope;
 | 
						|
} gOpcodeSizesScopeTable[] = {
 | 
						|
  { 0, 0 },                                    // EFI_IFR_INVALID - 0x00
 | 
						|
  { sizeof (EFI_IFR_FORM), 1 },                // EFI_IFR_FORM_OP
 | 
						|
  { sizeof (EFI_IFR_SUBTITLE), 1 },            // EFI_IFR_SUBTITLE_OP
 | 
						|
  { sizeof (EFI_IFR_TEXT), 0 },                // EFI_IFR_TEXT_OP
 | 
						|
  { sizeof (EFI_IFR_IMAGE), 0 },               // EFI_IFR_IMAGE_OP
 | 
						|
  { sizeof (EFI_IFR_ONE_OF), 1 },              // EFI_IFR_ONE_OF_OP - 0x05
 | 
						|
  { sizeof (EFI_IFR_CHECKBOX), 1},             // EFI_IFR_CHECKBOX_OP
 | 
						|
  { sizeof (EFI_IFR_NUMERIC), 1 },             // EFI_IFR_NUMERIC_OP
 | 
						|
  { sizeof (EFI_IFR_PASSWORD), 1 },            // EFI_IFR_PASSWORD_OP
 | 
						|
  { sizeof (EFI_IFR_ONE_OF_OPTION), 0 },       // EFI_IFR_ONE_OF_OPTION_OP
 | 
						|
  { sizeof (EFI_IFR_SUPPRESS_IF), 1 },         // EFI_IFR_SUPPRESS_IF - 0x0A
 | 
						|
  { sizeof (EFI_IFR_LOCKED), 0 },              // EFI_IFR_LOCKED_OP
 | 
						|
  { sizeof (EFI_IFR_ACTION), 1 },              // EFI_IFR_ACTION_OP
 | 
						|
  { sizeof (EFI_IFR_RESET_BUTTON), 1 },        // EFI_IFR_RESET_BUTTON_OP
 | 
						|
  { sizeof (EFI_IFR_FORM_SET), 1 },            // EFI_IFR_FORM_SET_OP -0xE
 | 
						|
  { sizeof (EFI_IFR_REF), 0 },                 // EFI_IFR_REF_OP
 | 
						|
  { sizeof (EFI_IFR_NO_SUBMIT_IF), 1},         // EFI_IFR_NO_SUBMIT_IF_OP -0x10
 | 
						|
  { sizeof (EFI_IFR_INCONSISTENT_IF), 1 },     // EFI_IFR_INCONSISTENT_IF_OP
 | 
						|
  { sizeof (EFI_IFR_EQ_ID_VAL), 0 },           // EFI_IFR_EQ_ID_VAL_OP
 | 
						|
  { sizeof (EFI_IFR_EQ_ID_ID), 0 },            // EFI_IFR_EQ_ID_ID_OP
 | 
						|
  { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 },      // EFI_IFR_EQ_ID_LIST_OP - 0x14
 | 
						|
  { sizeof (EFI_IFR_AND), 0 },                 // EFI_IFR_AND_OP
 | 
						|
  { sizeof (EFI_IFR_OR), 0 },                  // EFI_IFR_OR_OP
 | 
						|
  { sizeof (EFI_IFR_NOT), 0 },                 // EFI_IFR_NOT_OP
 | 
						|
  { sizeof (EFI_IFR_RULE), 1 },                // EFI_IFR_RULE_OP
 | 
						|
  { sizeof (EFI_IFR_GRAY_OUT_IF), 1 },         // EFI_IFR_GRAYOUT_IF_OP - 0x19
 | 
						|
  { sizeof (EFI_IFR_DATE), 1 },                // EFI_IFR_DATE_OP
 | 
						|
  { sizeof (EFI_IFR_TIME), 1 },                // EFI_IFR_TIME_OP
 | 
						|
  { sizeof (EFI_IFR_STRING), 1 },              // EFI_IFR_STRING_OP
 | 
						|
  { sizeof (EFI_IFR_REFRESH), 0 },             // EFI_IFR_REFRESH_OP
 | 
						|
  { sizeof (EFI_IFR_DISABLE_IF), 1 },          // EFI_IFR_DISABLE_IF_OP - 0x1E
 | 
						|
  { 0, 0 },                                    // 0x1F
 | 
						|
  { sizeof (EFI_IFR_TO_LOWER), 0 },            // EFI_IFR_TO_LOWER_OP - 0x20
 | 
						|
  { sizeof (EFI_IFR_TO_UPPER), 0 },            // EFI_IFR_TO_UPPER_OP - 0x21
 | 
						|
  { sizeof (EFI_IFR_MAP), 1 },                 // EFI_IFR_MAP - 0x22
 | 
						|
  { sizeof (EFI_IFR_ORDERED_LIST), 1 },        // EFI_IFR_ORDERED_LIST_OP - 0x23
 | 
						|
  { sizeof (EFI_IFR_VARSTORE), 0 },            // EFI_IFR_VARSTORE_OP
 | 
						|
  { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP
 | 
						|
  { sizeof (EFI_IFR_VARSTORE_EFI), 0 },        // EFI_IFR_VARSTORE_EFI_OP
 | 
						|
  { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 },     // EFI_IFR_VARSTORE_DEVICE_OP
 | 
						|
  { sizeof (EFI_IFR_VERSION), 0 },             // EFI_IFR_VERSION_OP - 0x28
 | 
						|
  { sizeof (EFI_IFR_END), 0 },                 // EFI_IFR_END_OP
 | 
						|
  { sizeof (EFI_IFR_MATCH), 0 },               // EFI_IFR_MATCH_OP - 0x2A
 | 
						|
  { sizeof (EFI_IFR_GET), 0 },                 // EFI_IFR_GET - 0x2B
 | 
						|
  { sizeof (EFI_IFR_SET), 0 },                 // EFI_IFR_SET - 0x2C
 | 
						|
  { sizeof (EFI_IFR_READ), 0 },                // EFI_IFR_READ - 0x2D
 | 
						|
  { sizeof (EFI_IFR_WRITE), 0 },               // EFI_IFR_WRITE - 0x2E
 | 
						|
  { sizeof (EFI_IFR_EQUAL), 0 },               // EFI_IFR_EQUAL_OP - 0x2F
 | 
						|
  { sizeof (EFI_IFR_NOT_EQUAL), 0 },           // EFI_IFR_NOT_EQUAL_OP
 | 
						|
  { sizeof (EFI_IFR_GREATER_THAN), 0 },        // EFI_IFR_GREATER_THAN_OP
 | 
						|
  { sizeof (EFI_IFR_GREATER_EQUAL), 0 },       // EFI_IFR_GREATER_EQUAL_OP
 | 
						|
  { sizeof (EFI_IFR_LESS_THAN), 0 },           // EFI_IFR_LESS_THAN_OP
 | 
						|
  { sizeof (EFI_IFR_LESS_EQUAL), 0 },          // EFI_IFR_LESS_EQUAL_OP - 0x34
 | 
						|
  { sizeof (EFI_IFR_BITWISE_AND), 0 },         // EFI_IFR_BITWISE_AND_OP
 | 
						|
  { sizeof (EFI_IFR_BITWISE_OR), 0 },          // EFI_IFR_BITWISE_OR_OP
 | 
						|
  { sizeof (EFI_IFR_BITWISE_NOT), 0 },         // EFI_IFR_BITWISE_NOT_OP
 | 
						|
  { sizeof (EFI_IFR_SHIFT_LEFT), 0 },          // EFI_IFR_SHIFT_LEFT_OP
 | 
						|
  { sizeof (EFI_IFR_SHIFT_RIGHT), 0 },         // EFI_IFR_SHIFT_RIGHT_OP
 | 
						|
  { sizeof (EFI_IFR_ADD), 0 },                 // EFI_IFR_ADD_OP - 0x3A
 | 
						|
  { sizeof (EFI_IFR_SUBTRACT), 0 },            // EFI_IFR_SUBTRACT_OP
 | 
						|
  { sizeof (EFI_IFR_MULTIPLY), 0 },            // EFI_IFR_MULTIPLY_OP
 | 
						|
  { sizeof (EFI_IFR_DIVIDE), 0 },              // EFI_IFR_DIVIDE_OP
 | 
						|
  { sizeof (EFI_IFR_MODULO), 0 },              // EFI_IFR_MODULO_OP - 0x3E
 | 
						|
  { sizeof (EFI_IFR_RULE_REF), 0 },            // EFI_IFR_RULE_REF_OP
 | 
						|
  { sizeof (EFI_IFR_QUESTION_REF1), 0 },       // EFI_IFR_QUESTION_REF1_OP
 | 
						|
  { sizeof (EFI_IFR_QUESTION_REF2), 0 },       // EFI_IFR_QUESTION_REF2_OP - 0x41
 | 
						|
  { sizeof (EFI_IFR_UINT8), 0},                // EFI_IFR_UINT8
 | 
						|
  { sizeof (EFI_IFR_UINT16), 0},               // EFI_IFR_UINT16
 | 
						|
  { sizeof (EFI_IFR_UINT32), 0},               // EFI_IFR_UINT32
 | 
						|
  { sizeof (EFI_IFR_UINT64), 0},               // EFI_IFR_UTNT64
 | 
						|
  { sizeof (EFI_IFR_TRUE), 0 },                // EFI_IFR_TRUE_OP - 0x46
 | 
						|
  { sizeof (EFI_IFR_FALSE), 0 },               // EFI_IFR_FALSE_OP
 | 
						|
  { sizeof (EFI_IFR_TO_UINT), 0 },             // EFI_IFR_TO_UINT_OP
 | 
						|
  { sizeof (EFI_IFR_TO_STRING), 0 },           // EFI_IFR_TO_STRING_OP
 | 
						|
  { sizeof (EFI_IFR_TO_BOOLEAN), 0 },          // EFI_IFR_TO_BOOLEAN_OP
 | 
						|
  { sizeof (EFI_IFR_MID), 0 },                 // EFI_IFR_MID_OP
 | 
						|
  { sizeof (EFI_IFR_FIND), 0 },                // EFI_IFR_FIND_OP
 | 
						|
  { sizeof (EFI_IFR_TOKEN), 0 },               // EFI_IFR_TOKEN_OP
 | 
						|
  { sizeof (EFI_IFR_STRING_REF1), 0 },         // EFI_IFR_STRING_REF1_OP - 0x4E
 | 
						|
  { sizeof (EFI_IFR_STRING_REF2), 0 },         // EFI_IFR_STRING_REF2_OP
 | 
						|
  { sizeof (EFI_IFR_CONDITIONAL), 0 },         // EFI_IFR_CONDITIONAL_OP
 | 
						|
  { sizeof (EFI_IFR_QUESTION_REF3), 0 },       // EFI_IFR_QUESTION_REF3_OP
 | 
						|
  { sizeof (EFI_IFR_ZERO), 0 },                // EFI_IFR_ZERO_OP
 | 
						|
  { sizeof (EFI_IFR_ONE), 0 },                 // EFI_IFR_ONE_OP
 | 
						|
  { sizeof (EFI_IFR_ONES), 0 },                // EFI_IFR_ONES_OP
 | 
						|
  { sizeof (EFI_IFR_UNDEFINED), 0 },           // EFI_IFR_UNDEFINED_OP
 | 
						|
  { sizeof (EFI_IFR_LENGTH), 0 },              // EFI_IFR_LENGTH_OP
 | 
						|
  { sizeof (EFI_IFR_DUP), 0 },                 // EFI_IFR_DUP_OP - 0x57
 | 
						|
  { sizeof (EFI_IFR_THIS), 0 },                // EFI_IFR_THIS_OP
 | 
						|
  { sizeof (EFI_IFR_SPAN), 0 },                // EFI_IFR_SPAN_OP
 | 
						|
  { sizeof (EFI_IFR_VALUE), 1 },               // EFI_IFR_VALUE_OP
 | 
						|
  { sizeof (EFI_IFR_DEFAULT), 0 },             // EFI_IFR_DEFAULT_OP
 | 
						|
  { sizeof (EFI_IFR_DEFAULTSTORE), 0 },        // EFI_IFR_DEFAULTSTORE_OP - 0x5C
 | 
						|
  { sizeof (EFI_IFR_FORM_MAP), 1},             // EFI_IFR_FORM_MAP_OP - 0x5D
 | 
						|
  { sizeof (EFI_IFR_CATENATE), 0 },            // EFI_IFR_CATENATE_OP
 | 
						|
  { sizeof (EFI_IFR_GUID), 0 },                // EFI_IFR_GUID_OP
 | 
						|
  { sizeof (EFI_IFR_SECURITY), 0 },            // EFI_IFR_SECURITY_OP - 0x60
 | 
						|
  { sizeof (EFI_IFR_MODAL_TAG), 0},            // EFI_IFR_MODAL_TAG_OP - 0x61
 | 
						|
  { sizeof (EFI_IFR_REFRESH_ID), 0},           // EFI_IFR_REFRESH_ID_OP - 0x62
 | 
						|
  { sizeof (EFI_IFR_WARNING_IF), 1},           // EFI_IFR_WARNING_IF_OP - 0x63
 | 
						|
  { sizeof (EFI_IFR_MATCH2), 0 },              // EFI_IFR_MATCH2_OP - 0x64
 | 
						|
};
 | 
						|
 | 
						|
#ifdef CIFROBJ_DEUBG
 | 
						|
static struct {
 | 
						|
  CHAR8 *mIfrName;
 | 
						|
} gIfrObjPrintDebugTable[] = {
 | 
						|
  "EFI_IFR_INVALID",    "EFI_IFR_FORM",                 "EFI_IFR_SUBTITLE",      "EFI_IFR_TEXT",            "EFI_IFR_IMAGE",         "EFI_IFR_ONE_OF",
 | 
						|
  "EFI_IFR_CHECKBOX",   "EFI_IFR_NUMERIC",              "EFI_IFR_PASSWORD",      "EFI_IFR_ONE_OF_OPTION",   "EFI_IFR_SUPPRESS_IF",   "EFI_IFR_LOCKED",
 | 
						|
  "EFI_IFR_ACTION",     "EFI_IFR_RESET_BUTTON",         "EFI_IFR_FORM_SET",      "EFI_IFR_REF",             "EFI_IFR_NO_SUBMIT_IF",  "EFI_IFR_INCONSISTENT_IF",
 | 
						|
  "EFI_IFR_EQ_ID_VAL",  "EFI_IFR_EQ_ID_ID",             "EFI_IFR_EQ_ID_LIST",    "EFI_IFR_AND",             "EFI_IFR_OR",            "EFI_IFR_NOT",
 | 
						|
  "EFI_IFR_RULE",       "EFI_IFR_GRAY_OUT_IF",          "EFI_IFR_DATE",          "EFI_IFR_TIME",            "EFI_IFR_STRING",        "EFI_IFR_REFRESH",
 | 
						|
  "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID",              "EFI_IFR_TO_LOWER",      "EFI_IFR_TO_UPPER",        "EFI_IFR_MAP",           "EFI_IFR_ORDERED_LIST",
 | 
						|
  "EFI_IFR_VARSTORE",   "EFI_IFR_VARSTORE_NAME_VALUE",  "EFI_IFR_VARSTORE_EFI",  "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION",       "EFI_IFR_END",
 | 
						|
  "EFI_IFR_MATCH",      "EFI_IFR_GET",                  "EFI_IFR_SET",           "EFI_IFR_READ",            "EFI_IFR_WRITE",         "EFI_IFR_EQUAL",
 | 
						|
  "EFI_IFR_NOT_EQUAL",  "EFI_IFR_GREATER_THAN",         "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN",       "EFI_IFR_LESS_EQUAL",    "EFI_IFR_BITWISE_AND",
 | 
						|
  "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT",          "EFI_IFR_SHIFT_LEFT",    "EFI_IFR_SHIFT_RIGHT",     "EFI_IFR_ADD",           "EFI_IFR_SUBTRACT",
 | 
						|
  "EFI_IFR_MULTIPLY",   "EFI_IFR_DIVIDE",               "EFI_IFR_MODULO",        "EFI_IFR_RULE_REF",        "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",
 | 
						|
  "EFI_IFR_UINT8",      "EFI_IFR_UINT16",               "EFI_IFR_UINT32",        "EFI_IFR_UINT64",          "EFI_IFR_TRUE",          "EFI_IFR_FALSE",
 | 
						|
  "EFI_IFR_TO_UINT",    "EFI_IFR_TO_STRING",            "EFI_IFR_TO_BOOLEAN",    "EFI_IFR_MID",             "EFI_IFR_FIND",          "EFI_IFR_TOKEN",
 | 
						|
  "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2",          "EFI_IFR_CONDITIONAL",   "EFI_IFR_QUESTION_REF3",   "EFI_IFR_ZERO",          "EFI_IFR_ONE",
 | 
						|
  "EFI_IFR_ONES",       "EFI_IFR_UNDEFINED",            "EFI_IFR_LENGTH",        "EFI_IFR_DUP",             "EFI_IFR_THIS",          "EFI_IFR_SPAN",
 | 
						|
  "EFI_IFR_VALUE",      "EFI_IFR_DEFAULT",              "EFI_IFR_DEFAULTSTORE",  "EFI_IFR_FORM_MAP",        "EFI_IFR_CATENATE",      "EFI_IFR_GUID",
 | 
						|
  "EFI_IFR_SECURITY",   "EFI_IFR_MODAL_TAG",            "EFI_IFR_REFRESH_ID",    "EFI_IFR_WARNING_IF",      "EFI_IFR_MATCH2",
 | 
						|
};
 | 
						|
 | 
						|
VOID
 | 
						|
CIFROBJ_DEBUG_PRINT (
 | 
						|
  IN UINT8 OpCode
 | 
						|
  )
 | 
						|
{
 | 
						|
  printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);
 | 
						|
}
 | 
						|
#else
 | 
						|
 | 
						|
#define CIFROBJ_DEBUG_PRINT(OpCode)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
BOOLEAN gCreateOp = TRUE;
 | 
						|
 | 
						|
CIfrObj::CIfrObj (
 | 
						|
  IN  UINT8   OpCode,
 | 
						|
  OUT CHAR8   **IfrObj,
 | 
						|
  IN  UINT8   ObjBinLen,
 | 
						|
  IN  BOOLEAN DelayEmit
 | 
						|
  )
 | 
						|
{
 | 
						|
  mDelayEmit   = DelayEmit;
 | 
						|
  mPkgOffset   = gCFormPkg.GetPkgLength ();
 | 
						|
  mObjBinLen   = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;
 | 
						|
  mObjBinBuf   = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];
 | 
						|
  mRecordIdx   = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;
 | 
						|
  mLineNo      = 0;
 | 
						|
 | 
						|
  assert (mObjBinBuf != NULL);
 | 
						|
 | 
						|
  if (IfrObj != NULL) {
 | 
						|
    *IfrObj    = mObjBinBuf;
 | 
						|
  }
 | 
						|
 | 
						|
  CIFROBJ_DEBUG_PRINT (OpCode);
 | 
						|
}
 | 
						|
 | 
						|
CIfrObj::~CIfrObj (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {
 | 
						|
    _EMIT_PENDING_OBJ ();
 | 
						|
  }
 | 
						|
 | 
						|
  gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The definition of CIfrObj's member function
 | 
						|
 */
 | 
						|
UINT8 gScopeCount = 0;
 | 
						|
 | 
						|
CIfrOpHeader::CIfrOpHeader (
 | 
						|
  IN UINT8 OpCode,
 | 
						|
  IN VOID *StartAddr,
 | 
						|
  IN UINT8 Length
 | 
						|
  ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr)
 | 
						|
{
 | 
						|
  mHeader->OpCode = OpCode;
 | 
						|
  mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;
 | 
						|
  mHeader->Scope  = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
CIfrOpHeader::CIfrOpHeader (
 | 
						|
  IN CIfrOpHeader &OpHdr
 | 
						|
  )
 | 
						|
{
 | 
						|
  mHeader = OpHdr.mHeader;
 | 
						|
}
 | 
						|
 | 
						|
UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };
 |