summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp')
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp2457
1 files changed, 2457 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
new file mode 100644
index 00000000..e80426f6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
@@ -0,0 +1,2457 @@
+/** @file
+
+ The definition of CFormPkg's member function
+
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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;
+ }
+
+
+ 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 valid 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) {
+ 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 Inconsistent 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, };