summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp')
-rw-r--r--BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp788
1 files changed, 724 insertions, 64 deletions
diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
index 892b7b8fc7..db1e4bdd1e 100644
--- a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
+++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
@@ -652,11 +652,12 @@ CFormPkg::GetBufAddrBaseOnOffset (
EFI_VFR_RETURN_CODE
CFormPkg::AdjustDynamicInsertOpcode (
- IN CHAR8 *LastFormEndAddr,
- IN CHAR8 *InsertOpcodeAddr
+ IN CHAR8 *InserPositionAddr,
+ IN CHAR8 *InsertOpcodeAddr,
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
)
{
- SBufferNode *LastFormEndNode;
+ SBufferNode *InserPositionNode;
SBufferNode *InsertOpcodeNode;
SBufferNode *NewRestoreNodeBegin;
SBufferNode *NewRestoreNodeEnd;
@@ -666,53 +667,53 @@ CFormPkg::AdjustDynamicInsertOpcode (
NewRestoreNodeEnd = NULL;
- LastFormEndNode = GetBinBufferNodeForAddr(LastFormEndAddr);
+ InserPositionNode = GetBinBufferNodeForAddr(InserPositionAddr);
InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);
- if (LastFormEndNode == InsertOpcodeNode) {
+ if (InserPositionNode == InsertOpcodeNode) {
//
// Create New Node to save the restore opcode.
//
- NeedRestoreCodeLen = InsertOpcodeAddr - LastFormEndAddr;
+ NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;
gAdjustOpcodeLen = NeedRestoreCodeLen;
NewRestoreNodeBegin = CreateNewNode ();
if (NewRestoreNodeBegin == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
- memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
+ memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
//
// Override the restore buffer data.
//
- memmove (LastFormEndAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
+ memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;
memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);
} else {
//
// Create New Node to save the restore opcode.
//
- NeedRestoreCodeLen = LastFormEndNode->mBufferFree - LastFormEndAddr;
+ NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;
gAdjustOpcodeLen = NeedRestoreCodeLen;
NewRestoreNodeBegin = CreateNewNode ();
if (NewRestoreNodeBegin == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
- memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
+ memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
//
// Override the restore buffer data.
//
- LastFormEndNode->mBufferFree -= NeedRestoreCodeLen;
+ InserPositionNode->mBufferFree -= NeedRestoreCodeLen;
//
// Link the restore data to new node.
//
- NewRestoreNodeBegin->mNext = LastFormEndNode->mNext;
+ NewRestoreNodeBegin->mNext = InserPositionNode->mNext;
//
// Count the Adjust opcode len.
//
- TmpNode = LastFormEndNode->mNext;
+ TmpNode = InserPositionNode->mNext;
while (TmpNode != InsertOpcodeNode) {
gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;
TmpNode = TmpNode->mNext;
@@ -740,50 +741,64 @@ CFormPkg::AdjustDynamicInsertOpcode (
// Insert the last restore data node.
//
TmpNode = GetNodeBefore (InsertOpcodeNode);
- if (TmpNode == LastFormEndNode) {
+ if (TmpNode == InserPositionNode) {
NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;
} else {
TmpNode->mNext = NewRestoreNodeEnd;
}
//
- // Connect the dynamic opcode node to the node before last form end node.
+ // Connect the dynamic opcode node to the node after InserPositionNode.
//
- LastFormEndNode->mNext = InsertOpcodeNode;
+ InserPositionNode->mNext = InsertOpcodeNode;
}
}
- if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
+ if (CreateOpcodeAfterParsingVfr) {
//
- // End form set opcode all in the mBufferNodeQueueTail node.
+ // 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.
//
- 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;
+ mBufferNodeQueueTail = NewRestoreNodeEnd;
} else {
- NewRestoreNodeBegin->mNext = NewLastEndNode;
+ 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 = NewLastEndNode;
- } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
- TmpNode = GetNodeBefore(mBufferNodeQueueTail);
- TmpNode->mNext = NewRestoreNodeBegin;
- if (NewRestoreNodeEnd != NULL) {
- NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
- } else {
- NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
+ 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);
+ TmpNode->mNext = NewRestoreNodeBegin;
+ if (NewRestoreNodeEnd != NULL) {
+ NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
+ } else {
+ NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
+ }
}
}
-
+ mCurrBufferNode = mBufferNodeQueueTail;
return VFR_RETURN_SUCCESS;
}
@@ -983,6 +998,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 (
@@ -1233,63 +1252,131 @@ CIfrRecordInfoDB::GetRecordInfoFromOffset (
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
-
- | form end opcode + end of if opcode for form ... + Dynamic opcode + form set end opcode |
-
+
+ |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|
+
To
-
- | Dynamic opcode + form end opcode + end of if opcode for form ... + form set end opcode |
-*/
+ |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 (
- VOID
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
)
{
UINT32 OpcodeOffset;
SIfrRecord *pNode, *pPreNode;
- SIfrRecord *pStartNode, *pNodeBeforeStart;
- SIfrRecord *pEndNode;
-
- pStartNode = NULL;
- pEndNode = NULL;
- OpcodeOffset = 0;
+ SIfrRecord *pAdjustNode, *pNodeBeforeAdjust;
+ SIfrRecord *pNodeBeforeDynamic;
+
+ pAdjustNode = NULL;
+ pNodeBeforeDynamic = NULL;
+ OpcodeOffset = 0;
//
- // Base on the offset info to get the node.
+ // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,
+ // and the node before pDynamicOpcodeNode.
//
- for (pNode = mIfrRecordListHead; pNode->mNext != NULL; pPreNode = pNode,pNode = pNode->mNext) {
+ for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {
if (OpcodeOffset == gAdjustOpcodeOffset) {
- pStartNode = pNode;
- pNodeBeforeStart = pPreNode;
+ pAdjustNode = pNode;
+ pNodeBeforeAdjust = pPreNode;
} else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {
- pEndNode = pPreNode;
+ pNodeBeforeDynamic = pPreNode;
+ }
+ if (pNode->mNext != NULL) {
+ pPreNode = pNode;
}
-
OpcodeOffset += pNode->mBinBufLen;
}
//
- // Check the value.
+ // Check the nodes whether exist.
//
- if (pEndNode == NULL || pStartNode == NULL) {
+ if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL) {
return FALSE;
}
//
// Adjust the node. pPreNode save the Node before mIfrRecordListTail
//
- pNodeBeforeStart->mNext = pEndNode->mNext;
- pPreNode->mNext = pStartNode;
- pEndNode->mNext = 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, "Error", "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
@@ -1522,6 +1609,579 @@ CIfrRecordInfoDB::IfrRecordAdjust (
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;
+ 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++;
+ }
+ //
+ // 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);
+ 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