From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 2457 ++++++++++++++++++++ 1 file changed, 2457 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp') 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.
+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(); + + //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(); + 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, }; -- cgit v1.2.3