X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FVfrCompile%2FVfrFormPkg.cpp;h=090ee13ef9da2e1b2402294d4d1908d50e5f8999;hp=2e859b8dfa626826c668d2697bc6de921af26bd2;hb=5397bd425eba0cd00c5f76c8d35f328ca625db0e;hpb=64b2609fcff9d6412eea4c74c8e74bed33dc3235 diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp index 2e859b8dfa..090ee13ef9 100644 --- a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp +++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp @@ -2,7 +2,7 @@ The definition of CFormPkg's member function -Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include "stdio.h" +#include "assert.h" #include "VfrFormPkg.h" /* @@ -55,13 +56,13 @@ SPendingAssign::~SPendingAssign ( ) { if (mKey != NULL) { - delete mKey; + delete[] mKey; } mAddr = NULL; mLen = 0; mLineNo = 0; if (mMsg != NULL) { - delete mMsg; + delete[] mMsg; } mNext = NULL; } @@ -82,7 +83,7 @@ SPendingAssign::AssignValue ( IN UINT32 Len ) { - memcpy (mAddr, Addr, (mLen < Len ? mLen : Len)); + memmove (mAddr, Addr, (mLen < Len ? mLen : Len)); mFlag = ASSIGNED; } @@ -95,7 +96,7 @@ SPendingAssign::GetKey ( } CFormPkg::CFormPkg ( - IN UINT32 BufferSize = 4096 + IN UINT32 BufferSize ) { CHAR8 *BufferStart; @@ -103,8 +104,13 @@ CFormPkg::CFormPkg ( SBufferNode *Node; mPkgLength = 0; + mBufferSize = 0; mBufferNodeQueueHead = NULL; + mBufferNodeQueueTail = NULL; mCurrBufferNode = NULL; + mReadBufferNode = NULL; + mReadBufferOffset = 0; + PendingAssignList = NULL; Node = new SBufferNode; if (Node == NULL) { @@ -112,6 +118,7 @@ CFormPkg::CFormPkg ( } BufferStart = new CHAR8[BufferSize]; if (BufferStart == NULL) { + delete Node; return; } BufferEnd = BufferStart + BufferSize; @@ -152,12 +159,39 @@ CFormPkg::~CFormPkg () 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; + CHAR8 *BinBuffer = NULL; + SBufferNode *Node = NULL; if ((Len == 0) || (Len > mBufferSize)) { return NULL; @@ -167,24 +201,11 @@ CFormPkg::IfrBinBufferGet ( BinBuffer = mCurrBufferNode->mBufferFree; mCurrBufferNode->mBufferFree += Len; } else { - SBufferNode *Node; - - Node = new SBufferNode; + Node = CreateNewNode (); 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; - } - if (mBufferNodeQueueTail == NULL) { mBufferNodeQueueHead = mBufferNodeQueueTail = Node; } else { @@ -245,7 +266,7 @@ CFormPkg::Read ( } if (mReadBufferNode == NULL) { - return 0; + return 0; } for (Index = 0; Index < Size; Index++) { @@ -256,7 +277,7 @@ CFormPkg::Read ( return Index; } else { mReadBufferOffset = 0; - Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; + Index --; } } } @@ -402,6 +423,9 @@ CFormPkg::_WRITE_PKG_END ( } #define BYTES_PRE_LINE 0x10 +UINT32 gAdjustOpcodeOffset = 0; +BOOLEAN gNeedAdjustOpcode = FALSE; +UINT32 gAdjustOpcodeLen = 0; EFI_VFR_RETURN_CODE CFormPkg::GenCFile ( @@ -548,13 +572,257 @@ CFormPkg::PendingAssignPrintAll ( } } +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 + IN UINT32 LineNo, + OUT CHAR8 **InsertOpcodeAddr ) { SPendingAssign *pNode; @@ -563,8 +831,12 @@ CFormPkg::DeclarePendingQuestion ( 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 @@ -572,6 +844,7 @@ CFormPkg::DeclarePendingQuestion ( // DisableIf CIfrDisableIf DIObj; DIObj.SetLineNo (LineNo); + *InsertOpcodeAddr = DIObj.GetObjBinAddr(); //TrueOpcode CIfrTrue TObj (LineNo); @@ -579,14 +852,8 @@ CFormPkg::DeclarePendingQuestion ( // Declare Numeric qeustion for each undefined question. for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { if (pNode->mFlag == PENDING) { - CIfrNumeric CNObj; EFI_VARSTORE_INFO Info; - EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; - - CNObj.SetLineNo (LineNo); - CNObj.SetPrompt (0x0); - CNObj.SetHelp (0x0); - + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; // // Register this question, assume it is normal question, not date or time question // @@ -611,45 +878,29 @@ CFormPkg::DeclarePendingQuestion ( // // Get VarStoreType // - ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); - if (ReturnCode == VFR_RETURN_UNDEFINED) { - lCVfrDataStorage.DeclareBufferVarStore ( - FName, - LocalFormSetGuid, - &lCVfrVarDataTypeDB, - FName, - EFI_VARSTORE_ID_INVALID, - FALSE - ); - ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); - } - if (ReturnCode != VFR_RETURN_SUCCESS) { - gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); - return ReturnCode; - } - 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) { + } 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 (FName, &SName); + 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); - delete NewStr; + ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar); + delete[] NewStr; } } else { ReturnCode = VFR_RETURN_UNSUPPORTED; @@ -659,36 +910,65 @@ CFormPkg::DeclarePendingQuestion ( gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); return ReturnCode; } - - CNObj.SetQuestionId (QId); - CNObj.SetVarStoreInfo (&Info); // - // Numeric doesn't support BOOLEAN data type. - // BOOLEAN type has the same data size to UINT8. + // If the storage is bit fields, create Guid opcode to wrap the numeric opcode. // - if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) { - Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8; + if (Info.mIsBitVar) { + GuidObj = new CIfrGuid(0); + GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); + GuidObj->SetLineNo(LineNo); } - CNObj.SetFlags (0, Info.mVarType); + + CIfrNumeric CNObj; + CNObj.SetLineNo (LineNo); + CNObj.SetPrompt (0x0); + CNObj.SetHelp (0x0); + CNObj.SetQuestionId (QId); + CNObj.SetVarStoreInfo (&Info); + // - // Use maximum value not to limit the vaild value for the undefined question. + // 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. // - switch (Info.mVarType) { - case EFI_IFR_TYPE_NUM_SIZE_64: - CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0); - break; - case EFI_IFR_TYPE_NUM_SIZE_32: - CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0); - break; - case EFI_IFR_TYPE_NUM_SIZE_16: - CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0); - break; - case EFI_IFR_TYPE_NUM_SIZE_8: - CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0); - break; - default: - break; + if (Info.mIsBitVar) { + MaxValue = (1 << Info.mVarTotalSize) -1; + CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0); + ShrinkSize = 12; + LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize); + CNObj.SetFlagsForBitField (0, LFlags); + } else { + // + // Numeric doesn't support BOOLEAN data type. + // BOOLEAN type has the same data size to UINT8. + // + if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) { + Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8; + } + CNObj.SetFlags (0, Info.mVarType); + // + // Use maximum value not to limit the vaild value for the undefined question. + // + switch (Info.mVarType) { + case EFI_IFR_TYPE_NUM_SIZE_64: + CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0); + ShrinkSize = 0; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0); + ShrinkSize = 12; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0); + ShrinkSize = 18; + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0); + ShrinkSize = 21; + break; + default: + break; + } } + CNObj.ShrinkBinSize (ShrinkSize); // // For undefined Efi VarStore type question @@ -698,12 +978,22 @@ CFormPkg::DeclarePendingQuestion ( CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName); CVNObj.SetLineNo (LineNo); } - + // // End for Numeric // - CIfrEnd CEObj; + CIfrEnd CEObj; CEObj.SetLineNo (LineNo); + // + // End for Guided opcode + // + if (GuidObj != NULL) { + CIfrEnd CEObjGuid; + CEObjGuid.SetLineNo (LineNo); + GuidObj->SetScope(1); + delete GuidObj; + GuidObj = NULL; + } } } @@ -751,6 +1041,10 @@ CIfrRecordInfoDB::CIfrRecordInfoDB ( 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 ( @@ -949,6 +1243,7 @@ CIfrRecordInfoDB::CheckQuestionOpCode ( 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; @@ -983,6 +1278,163 @@ CIfrRecordInfoDB::GetOpcodeQuestionId ( 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 @@ -994,7 +1446,6 @@ CIfrRecordInfoDB::IfrRecordAdjust ( EFI_QUESTION_ID QuestionId; UINT32 StackCount; UINT32 QuestionScope; - UINT32 OpcodeOffset; CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, }; EFI_VFR_RETURN_CODE Status; @@ -1195,15 +1646,590 @@ CIfrRecordInfoDB::IfrRecordAdjust ( // Update Ifr Opcode Offset // if (Status == VFR_RETURN_SUCCESS) { - OpcodeOffset = 0; - for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { - pNode->mOffset = OpcodeOffset; - OpcodeOffset += pNode->mBinBufLen; - } + 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 @@ -1226,7 +2252,7 @@ CIfrObj::_EMIT_PENDING_OBJ ( // ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen); if (ObjBinBuf != NULL) { - memcpy (ObjBinBuf, mObjBinBuf, mObjBinLen); + memmove (ObjBinBuf, mObjBinBuf, mObjBinLen); } // @@ -1344,8 +2370,10 @@ static struct { { 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), 0}, // EFI_IFR_MODAL_OP - 0x61 + { 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 @@ -1368,7 +2396,7 @@ static struct { "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", "EFI_IFR_REFRESH_ID", + "EFI_IFR_SECURITY", "EFI_IFR_MODAL_TAG", "EFI_IFR_REFRESH_ID", "EFI_IFR_WARNING_IF", "EFI_IFR_MATCH2", }; VOID @@ -1398,6 +2426,9 @@ CIfrObj::CIfrObj ( 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;