]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
BaseTools/VfrCompile: Add two new option for VfrCompile
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrFormPkg.cpp
index 892b7b8fc7374794dedf3f34a2a9651ca9168f9a..db1e4bdd1e2e8c43331178dd0356cbb9c7a11ec9 100644 (file)
@@ -652,11 +652,12 @@ CFormPkg::GetBufAddrBaseOnOffset (
 \r
 EFI_VFR_RETURN_CODE\r
 CFormPkg::AdjustDynamicInsertOpcode (\r
-  IN CHAR8              *LastFormEndAddr,\r
-  IN CHAR8              *InsertOpcodeAddr\r
+  IN CHAR8              *InserPositionAddr,\r
+  IN CHAR8              *InsertOpcodeAddr,\r
+  IN BOOLEAN            CreateOpcodeAfterParsingVfr\r
   )\r
 {\r
-  SBufferNode *LastFormEndNode;\r
+  SBufferNode *InserPositionNode;\r
   SBufferNode *InsertOpcodeNode;\r
   SBufferNode *NewRestoreNodeBegin;\r
   SBufferNode *NewRestoreNodeEnd;\r
@@ -666,53 +667,53 @@ CFormPkg::AdjustDynamicInsertOpcode (
 \r
   NewRestoreNodeEnd = NULL;\r
 \r
-  LastFormEndNode  = GetBinBufferNodeForAddr(LastFormEndAddr);\r
+  InserPositionNode  = GetBinBufferNodeForAddr(InserPositionAddr);\r
   InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);\r
 \r
-  if (LastFormEndNode == InsertOpcodeNode) {\r
+  if (InserPositionNode == InsertOpcodeNode) {\r
     //\r
     // Create New Node to save the restore opcode.\r
     //\r
-    NeedRestoreCodeLen = InsertOpcodeAddr - LastFormEndAddr;\r
+    NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;\r
     gAdjustOpcodeLen   = NeedRestoreCodeLen;\r
     NewRestoreNodeBegin = CreateNewNode ();\r
     if (NewRestoreNodeBegin == NULL) {\r
       return VFR_RETURN_OUT_FOR_RESOURCES;\r
     }\r
-    memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);\r
+    memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);\r
     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;\r
 \r
     //\r
     // Override the restore buffer data.\r
     //\r
-    memmove (LastFormEndAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);\r
+    memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);\r
     InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;\r
     memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);\r
   } else {\r
     //\r
     // Create New Node to save the restore opcode.\r
     //\r
-    NeedRestoreCodeLen = LastFormEndNode->mBufferFree - LastFormEndAddr;\r
+    NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;\r
     gAdjustOpcodeLen   = NeedRestoreCodeLen;\r
     NewRestoreNodeBegin = CreateNewNode ();\r
     if (NewRestoreNodeBegin == NULL) {\r
       return VFR_RETURN_OUT_FOR_RESOURCES;\r
     }\r
-    memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);\r
+    memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);\r
     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;\r
     //\r
     // Override the restore buffer data.\r
     //\r
-    LastFormEndNode->mBufferFree -= NeedRestoreCodeLen;\r
+    InserPositionNode->mBufferFree -= NeedRestoreCodeLen;\r
     //\r
     // Link the restore data to new node.\r
     //\r
-    NewRestoreNodeBegin->mNext = LastFormEndNode->mNext;\r
+    NewRestoreNodeBegin->mNext = InserPositionNode->mNext;\r
 \r
     //\r
     // Count the Adjust opcode len.\r
     //\r
-    TmpNode = LastFormEndNode->mNext;\r
+    TmpNode = InserPositionNode->mNext;\r
     while (TmpNode != InsertOpcodeNode) {\r
       gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;\r
       TmpNode = TmpNode->mNext;\r
@@ -740,50 +741,64 @@ CFormPkg::AdjustDynamicInsertOpcode (
       // Insert the last restore data node.\r
       //\r
       TmpNode = GetNodeBefore (InsertOpcodeNode);\r
-      if (TmpNode == LastFormEndNode) {\r
+      if (TmpNode == InserPositionNode) {\r
         NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;\r
       } else {\r
         TmpNode->mNext = NewRestoreNodeEnd;\r
       }\r
       //\r
-      // Connect the dynamic opcode node to the node before last form end node.\r
+      // Connect the dynamic opcode node to the node after InserPositionNode.\r
       //\r
-      LastFormEndNode->mNext = InsertOpcodeNode;\r
+      InserPositionNode->mNext = InsertOpcodeNode;\r
     }\r
   }\r
 \r
-  if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {\r
+  if (CreateOpcodeAfterParsingVfr) {\r
     //\r
-    // End form set opcode all in the mBufferNodeQueueTail node.\r
+    // Th new opcodes were created after Parsing Vfr file,\r
+    // so the content in mBufferNodeQueueTail must be the new created opcodes.\r
+    // So connet the  NewRestoreNodeBegin to the tail and update the tail node.\r
     //\r
-    NewLastEndNode = CreateNewNode ();\r
-    if (NewLastEndNode == NULL) {\r
-      return VFR_RETURN_OUT_FOR_RESOURCES;\r
-    }\r
-    NewLastEndNode->mBufferStart[0] = 0x29;\r
-    NewLastEndNode->mBufferStart[1] = 0x02;\r
-    NewLastEndNode->mBufferFree += 2;\r
-\r
-    mBufferNodeQueueTail->mBufferFree -= 2;\r
-\r
     mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;\r
     if (NewRestoreNodeEnd != NULL) {\r
-      NewRestoreNodeEnd->mNext = NewLastEndNode;\r
+      mBufferNodeQueueTail = NewRestoreNodeEnd;\r
     } else {\r
-      NewRestoreNodeBegin->mNext = NewLastEndNode;\r
+      mBufferNodeQueueTail = NewRestoreNodeBegin;\r
     }\r
+  } else {\r
+    if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {\r
+      //\r
+      // End form set opcode all in the mBufferNodeQueueTail node.\r
+      //\r
+      NewLastEndNode = CreateNewNode ();\r
+      if (NewLastEndNode == NULL) {\r
+        return VFR_RETURN_OUT_FOR_RESOURCES;\r
+      }\r
+      NewLastEndNode->mBufferStart[0] = 0x29;\r
+      NewLastEndNode->mBufferStart[1] = 0x02;\r
+      NewLastEndNode->mBufferFree += 2;\r
 \r
-    mBufferNodeQueueTail = NewLastEndNode;\r
-  } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {\r
-    TmpNode = GetNodeBefore(mBufferNodeQueueTail);\r
-    TmpNode->mNext = NewRestoreNodeBegin;\r
-    if (NewRestoreNodeEnd != NULL) {\r
-      NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;\r
-    } else {\r
-      NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;\r
+      mBufferNodeQueueTail->mBufferFree -= 2;\r
+\r
+      mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;\r
+      if (NewRestoreNodeEnd != NULL) {\r
+        NewRestoreNodeEnd->mNext = NewLastEndNode;\r
+      } else {\r
+        NewRestoreNodeBegin->mNext = NewLastEndNode;\r
+      }\r
+\r
+      mBufferNodeQueueTail = NewLastEndNode;\r
+    } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {\r
+      TmpNode = GetNodeBefore(mBufferNodeQueueTail);\r
+      TmpNode->mNext = NewRestoreNodeBegin;\r
+      if (NewRestoreNodeEnd != NULL) {\r
+        NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;\r
+      } else {\r
+        NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;\r
+      }\r
     }\r
   }\r
-\r
+  mCurrBufferNode = mBufferNodeQueueTail;\r
   return VFR_RETURN_SUCCESS;\r
 }\r
 \r
@@ -983,6 +998,10 @@ CIfrRecordInfoDB::CIfrRecordInfoDB (
   mRecordCount       = EFI_IFR_RECORDINFO_IDX_START;\r
   mIfrRecordListHead = NULL;\r
   mIfrRecordListTail = NULL;\r
+  mAllDefaultTypeCount = 0;\r
+  for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) {\r
+    mAllDefaultIdArray[i] = 0xffff;\r
+  }\r
 }\r
 \r
 CIfrRecordInfoDB::~CIfrRecordInfoDB (\r
@@ -1233,63 +1252,131 @@ CIfrRecordInfoDB::GetRecordInfoFromOffset (
   return pNode;\r
 }\r
 \r
-/*\r
+/**\r
   Add just the op code position.\r
 \r
+  Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,\r
+  so pDynamicOpcodeNodes is before mIfrRecordListTail.\r
+\r
   From\r
-  \r
-  | form end opcode + end of if opcode for form ... + Dynamic opcode + form set end opcode |\r
-  \r
+\r
+  |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|\r
+\r
   To\r
-  \r
-  | Dynamic opcode + form end opcode + end of if opcode for form ... + form set end opcode |\r
 \r
-*/\r
+  |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|\r
+\r
+  Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,\r
+  so new records are appennded to the end of OriginalIfrRecordListTail.\r
+\r
+  From\r
+\r
+  |mIfrRecordListHead + ...+ pAdjustNode +  ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|\r
+\r
+  To\r
+\r
+  |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode +  ... + OriginalIfrRecordListTail|\r
+\r
+\r
+  @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.\r
+\r
+**/\r
 BOOLEAN\r
 CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (\r
-  VOID\r
+  IN BOOLEAN  CreateOpcodeAfterParsingVfr\r
   )\r
 {\r
   UINT32             OpcodeOffset;\r
   SIfrRecord         *pNode, *pPreNode;\r
-  SIfrRecord         *pStartNode, *pNodeBeforeStart;\r
-  SIfrRecord         *pEndNode;\r
-  \r
-  pStartNode = NULL;\r
-  pEndNode   = NULL;\r
-  OpcodeOffset = 0;\r
+  SIfrRecord         *pAdjustNode, *pNodeBeforeAdjust;\r
+  SIfrRecord         *pNodeBeforeDynamic;\r
+\r
+  pAdjustNode         = NULL;\r
+  pNodeBeforeDynamic  = NULL;\r
+  OpcodeOffset        = 0;\r
 \r
   //\r
-  // Base on the offset info to get the node.\r
+  // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,\r
+  // and the node before pDynamicOpcodeNode.\r
   //\r
-  for (pNode = mIfrRecordListHead; pNode->mNext != NULL; pPreNode = pNode,pNode = pNode->mNext) {\r
+  for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {\r
     if (OpcodeOffset == gAdjustOpcodeOffset) {\r
-      pStartNode       = pNode;\r
-      pNodeBeforeStart = pPreNode;\r
+      pAdjustNode       = pNode;\r
+      pNodeBeforeAdjust = pPreNode;\r
     } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {\r
-      pEndNode = pPreNode;\r
+      pNodeBeforeDynamic = pPreNode;\r
+    }\r
+    if (pNode->mNext != NULL) {\r
+      pPreNode = pNode;\r
     }\r
-\r
     OpcodeOffset += pNode->mBinBufLen;\r
   }\r
 \r
   //\r
-  // Check the value.\r
+  // Check the nodes whether exist.\r
   //\r
-  if (pEndNode == NULL || pStartNode == NULL) {\r
+  if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL) {\r
     return FALSE;\r
   }\r
 \r
   //\r
   // Adjust the node. pPreNode save the Node before mIfrRecordListTail\r
   //\r
-  pNodeBeforeStart->mNext = pEndNode->mNext;\r
-  pPreNode->mNext = pStartNode;\r
-  pEndNode->mNext = mIfrRecordListTail;\r
+  pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext;\r
+  if (CreateOpcodeAfterParsingVfr) {\r
+    //\r
+    // mIfrRecordListTail is the end of pDynamicNode (Case2).\r
+    //\r
+    mIfrRecordListTail->mNext = pAdjustNode;\r
+    mIfrRecordListTail = pNodeBeforeDynamic;\r
+    mIfrRecordListTail->mNext = NULL;\r
+  } else {\r
+    //\r
+    //pPreNode is the end of pDynamicNode(Case1).\r
+    //\r
+    pPreNode->mNext = pAdjustNode;\r
+    pNodeBeforeDynamic->mNext = mIfrRecordListTail;\r
+  }\r
 \r
   return TRUE;\r
 }\r
 \r
+/**\r
+  Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.\r
+\r
+  @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.\r
+\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (\r
+  IN BOOLEAN  CreateOpcodeAfterParsingVfr\r
+  )\r
+{\r
+  SIfrRecord          *pRecord;\r
+\r
+  //\r
+  // Base on the original offset info to update the record list.\r
+  //\r
+  if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) {\r
+    gCVfrErrorHandle.PrintMsg (0, "Error", "Can not find the adjust offset in the record.");\r
+  }\r
+\r
+  //\r
+  // Base on the opcode binary length to recalculate the offset for each opcode.\r
+  //\r
+  IfrAdjustOffsetForRecord();\r
+\r
+  //\r
+  // Base on the offset to find the binary address.\r
+  //\r
+  pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset);\r
+  while (pRecord != NULL) {\r
+    pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);\r
+    pRecord = pRecord->mNext;\r
+  }\r
+}\r
+\r
+\r
 VOID\r
 CIfrRecordInfoDB::IfrAdjustOffsetForRecord (\r
   VOID\r
@@ -1522,6 +1609,579 @@ CIfrRecordInfoDB::IfrRecordAdjust (
   return Status;\r
 }\r
 \r
+/**\r
+  When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not\r
+  given by expression, should save the default info for the Buffer VarStore.\r
+\r
+  @param  DefaultId           The default id.\r
+  @param  pQuestionNode       Point to the question opcode node.\r
+  @param  Value               The default value.\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (\r
+  IN  UINT16                  DefaultId,\r
+  IN  SIfrRecord              *pQuestionNode,\r
+  IN  EFI_IFR_TYPE_VALUE      Value\r
+  )\r
+{\r
+  CHAR8                   *VarStoreName = NULL;\r
+  EFI_VFR_VARSTORE_TYPE    VarStoreType  = EFI_VFR_VARSTORE_INVALID;\r
+  EFI_GUID                 *VarGuid      = NULL;\r
+  EFI_VARSTORE_INFO        VarInfo;\r
+  EFI_IFR_QUESTION_HEADER  *QuestionHead;\r
+  EFI_IFR_OP_HEADER        *pQuestionOpHead;\r
+\r
+  pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;\r
+  QuestionHead    = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1);\r
+\r
+  //\r
+  // Get the Var Store name and type.\r
+  //\r
+  gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName);\r
+  VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId);\r
+  VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId);\r
+\r
+  //\r
+  // Only for Buffer storage need to save the default info in the storage.\r
+  // Other type storage, just return.\r
+  //\r
+  if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) {\r
+    return;\r
+  } else {\r
+    VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset;\r
+    VarInfo.mVarStoreId = QuestionHead->VarStoreId;\r
+  }\r
+\r
+  //\r
+  // Get the buffer storage info about this question.\r
+  //\r
+  gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo);\r
+\r
+  //\r
+  // Add action.\r
+  //\r
+  gCVfrDefaultStore.BufferVarStoreAltConfigAdd (\r
+    DefaultId,\r
+    VarInfo,\r
+    VarStoreName,\r
+    VarGuid,\r
+    VarInfo.mVarType,\r
+    Value\r
+    );\r
+}\r
+\r
+/**\r
+  Record the number and default id of all defaultstore opcode.\r
+\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrGetDefaultStoreInfo (\r
+  VOID\r
+  )\r
+{\r
+  SIfrRecord             *pNode;\r
+  EFI_IFR_OP_HEADER      *pOpHead;\r
+  EFI_IFR_DEFAULTSTORE   *DefaultStore;\r
+\r
+  pNode                = mIfrRecordListHead;\r
+  mAllDefaultTypeCount = 0;\r
+\r
+  while (pNode != NULL) {\r
+    pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;\r
+\r
+    if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){\r
+      DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf;\r
+      mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId;\r
+    }\r
+    pNode = pNode->mNext;\r
+  }\r
+}\r
+\r
+/**\r
+  Create new default opcode record.\r
+\r
+  @param    Size            The new default opcode size.\r
+  @param    DefaultId       The new default id.\r
+  @param    Type            The new default type.\r
+  @param    LineNo          The line number of the new record.\r
+  @param    Value           The new default value.\r
+\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrCreateDefaultRecord(\r
+  IN UINT8               Size,\r
+  IN UINT16              DefaultId,\r
+  IN UINT8               Type,\r
+  IN UINT32              LineNo,\r
+  IN EFI_IFR_TYPE_VALUE  Value\r
+  )\r
+{\r
+  CIfrDefault   *DObj;\r
+  CIfrDefault2  *DObj2;\r
+\r
+  DObj  = NULL;\r
+  DObj2 = NULL;\r
+\r
+  if (Type == EFI_IFR_TYPE_OTHER) {\r
+    DObj2 = new CIfrDefault2 (Size);\r
+    DObj2->SetDefaultId(DefaultId);\r
+    DObj2->SetType(Type);\r
+    DObj2->SetLineNo(LineNo);\r
+    DObj2->SetScope (1);\r
+    delete DObj2;\r
+  } else {\r
+    DObj = new CIfrDefault (Size);\r
+    DObj->SetDefaultId(DefaultId);\r
+    DObj->SetType(Type);\r
+    DObj->SetLineNo(LineNo);\r
+    DObj->SetValue (Value);\r
+    delete DObj;\r
+  }\r
+}\r
+\r
+/**\r
+  Create new default opcode for question base on the QuestionDefaultInfo.\r
+\r
+  @param  pQuestionNode              Point to the question opcode Node.\r
+  @param  QuestionDefaultInfo        Point to the QuestionDefaultInfo for current question.\r
+\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrCreateDefaultForQuestion (\r
+  IN  SIfrRecord              *pQuestionNode,\r
+  IN  QuestionDefaultRecord   *QuestionDefaultInfo\r
+  )\r
+{\r
+  EFI_IFR_OP_HEADER      *pOpHead;\r
+  EFI_IFR_DEFAULT        *Default;\r
+  SIfrRecord             *pSNode;\r
+  SIfrRecord             *pENode;\r
+  SIfrRecord             *pDefaultNode;\r
+  CIfrObj                *Obj;\r
+  CHAR8                  *ObjBinBuf;\r
+  UINT8                  ScopeCount;\r
+  UINT8                  OpcodeNumber;\r
+  UINT8                  OpcodeCount;\r
+  UINT8                  DefaultSize;\r
+  EFI_IFR_ONE_OF_OPTION  *DefaultOptionOpcode;\r
+  EFI_IFR_TYPE_VALUE     CheckBoxDefaultValue;\r
+\r
+  CheckBoxDefaultValue.b = 1;\r
+  pOpHead                = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;\r
+  ScopeCount             = 0;\r
+  OpcodeCount            = 0;\r
+  Obj                    = NULL;\r
+\r
+  //\r
+  // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
+  //\r
+  gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset;\r
+  //\r
+  // Case 1:\r
+  // For oneof, the default with smallest default id is given by the option flag.\r
+  // So create the missing defaults base on the oneof option value(mDefaultValueRecord).\r
+  //\r
+  if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {\r
+    DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf;\r
+    DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value);\r
+    DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value);\r
+    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+        IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value);\r
+        //\r
+        // Save the new created default in the buffer storage.\r
+        //\r
+        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value);\r
+      }\r
+    }\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Case2:\r
+  // For checkbox, the default with smallest default id is given by the question flag.\r
+  // And create the missing defaults with true value.\r
+  //\r
+  if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {\r
+    DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN);\r
+    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+        IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue);\r
+        //\r
+        // Save the new created default.\r
+        //\r
+        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue);\r
+      }\r
+    }\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Case3:\r
+  // The default with smallest default id is given by the default opcode.\r
+  // So create the missing defaults base on the value in the default opcode.\r
+  //\r
+\r
+  //\r
+  // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.\r
+  //\r
+  pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord;\r
+  Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf;\r
+  //\r
+  // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
+  //\r
+  gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset;\r
+\r
+  if (Default->Type == EFI_IFR_TYPE_OTHER) {\r
+    //\r
+    // EFI_IFR_DEFAULT_2 opcode.\r
+    //\r
+    // Point to the first expression opcode.\r
+    //\r
+    pSNode = pDefaultNode->mNext;\r
+    ScopeCount++;\r
+    //\r
+    // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)\r
+    //\r
+    while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) {\r
+      pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
+      if (pOpHead->Scope == 1) {\r
+        ScopeCount++;\r
+      }\r
+      if (pOpHead->OpCode == EFI_IFR_END_OP) {\r
+        ScopeCount--;\r
+      }\r
+      pENode = pSNode;\r
+      pSNode = pSNode->mNext;\r
+      OpcodeCount++;\r
+    }\r
+    //\r
+    // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
+    //\r
+    gAdjustOpcodeOffset = pSNode->mOffset;\r
+    //\r
+    // Create new default opcode node for missing default.\r
+    //\r
+    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+      OpcodeNumber = OpcodeCount;\r
+      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+        IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value);\r
+        //\r
+        // Point to the first expression opcode node.\r
+        //\r
+        pSNode = pDefaultNode->mNext;\r
+        //\r
+        // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.\r
+        //\r
+        while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) {\r
+          pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
+          Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);\r
+          Obj->SetLineNo (pSNode->mLineNo);\r
+          ObjBinBuf = Obj->GetObjBinAddr();\r
+          memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);\r
+          delete Obj;\r
+          pSNode = pSNode->mNext;\r
+        }\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // EFI_IFR_DEFAULT opcode.\r
+    //\r
+    // Create new default opcode node for missing default.\r
+    //\r
+    for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+      if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+        IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value);\r
+        //\r
+        // Save the new created default in the buffer storage..\r
+        //\r
+        IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Parse the default information in a question, get the QuestionDefaultInfo.\r
+\r
+  @param  pQuestionNode          Point to the question record Node.\r
+  @param  QuestionDefaultInfo    On return, point to the QuestionDefaultInfo.\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(\r
+  IN  SIfrRecord              *pQuestionNode,\r
+  OUT QuestionDefaultRecord   *QuestionDefaultInfo\r
+  )\r
+{\r
+  SIfrRecord              *pSNode;\r
+  EFI_IFR_ONE_OF_OPTION   *OneofOptionOpcode;\r
+  EFI_IFR_OP_HEADER       *pSOpHead;\r
+  EFI_IFR_CHECKBOX        *CheckBoxOpcode;\r
+  EFI_IFR_DEFAULT         *DefaultOpcode;\r
+  BOOLEAN                 IsOneOfOpcode;\r
+  UINT16                  SmallestDefaultId;\r
+  UINT8                   ScopeCount;\r
+\r
+  SmallestDefaultId  = 0xffff;\r
+  IsOneOfOpcode      = FALSE;\r
+  ScopeCount         = 0;\r
+  pSNode             = pQuestionNode;\r
+\r
+  //\r
+  // Parse all the opcodes in the Question.\r
+  //\r
+  while (pSNode != NULL) {\r
+    pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
+    //\r
+    // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.\r
+    // Scopes may be nested within other scopes.\r
+    // When finishing parsing a question, the scope count must be zero.\r
+    //\r
+    if (pSOpHead->Scope == 1) {\r
+      ScopeCount++;\r
+    }\r
+    if (pSOpHead->OpCode == EFI_IFR_END_OP) {\r
+      ScopeCount--;\r
+    }\r
+    //\r
+    // Check whether finishing parsing a question.\r
+    //\r
+    if (ScopeCount == 0) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Record the default information in the question.\r
+    //\r
+    switch (pSOpHead->OpCode) {\r
+    case EFI_IFR_ONE_OF_OP:\r
+      IsOneOfOpcode = TRUE;\r
+      break;\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      //\r
+      // The default info of check box may be given by flag.\r
+      // So need to check the flag of check box.\r
+      //\r
+      CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf;\r
+      if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) {\r
+        //\r
+        // Check whether need to update the smallest default id.\r
+        //\r
+        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+        }\r
+        //\r
+        // Update the QuestionDefaultInfo.\r
+        //\r
+        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+              QuestionDefaultInfo->mDefaultNumber ++;\r
+              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
+            }\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) {\r
+        //\r
+        // Check whether need to update the smallest default id.\r
+        //\r
+        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+        }\r
+        //\r
+        // Update the QuestionDefaultInfo.\r
+        //\r
+        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+              QuestionDefaultInfo->mDefaultNumber ++;\r
+              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
+            }\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      break;\r
+    case EFI_IFR_ONE_OF_OPTION_OP:\r
+      if (!IsOneOfOpcode) {\r
+        //\r
+        // Only check the option in oneof.\r
+        //\r
+        break;\r
+      }\r
+      OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf;\r
+      if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {\r
+        //\r
+        // The option is used as the standard default.\r
+        // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
+        //\r
+        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+          QuestionDefaultInfo->mDefaultValueRecord = pSNode;\r
+        }\r
+        //\r
+        // Update the IsDefaultIdExist array in QuestionDefaultInfo.\r
+        //\r
+        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+              QuestionDefaultInfo->mDefaultNumber ++;\r
+              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
+            }\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) {\r
+        //\r
+        // This option is used as the manufacture default.\r
+        // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
+        //\r
+        if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+          SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+          QuestionDefaultInfo->mDefaultValueRecord = pSNode;\r
+        }\r
+        //\r
+        // Update the QuestionDefaultInfo.\r
+        //\r
+        for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
+          if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+            if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+              QuestionDefaultInfo->mDefaultNumber ++;\r
+              QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
+            }\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      break;\r
+    case EFI_IFR_DEFAULT_OP:\r
+      DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf;\r
+      //\r
+      // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
+      //\r
+      if (SmallestDefaultId >= DefaultOpcode->DefaultId ) {\r
+        SmallestDefaultId = DefaultOpcode->DefaultId;\r
+        QuestionDefaultInfo->mDefaultValueRecord= pSNode;\r
+        QuestionDefaultInfo->mIsDefaultOpcode= TRUE;\r
+      }\r
+      //\r
+      // Update the QuestionDefaultInfo.\r
+      //\r
+      for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){\r
+        if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) {\r
+          if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
+            QuestionDefaultInfo->mDefaultNumber ++;\r
+            QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+    //\r
+    // Parse next opcode in this question.\r
+    //\r
+    pSNode = pSNode->mNext;\r
+  }\r
+}\r
+\r
+/**\r
+  Check or add default for question if need.\r
+\r
+  This function will check the default info for question.\r
+  If the question has default, but the default number < defaultstore opcode number.\r
+  will do following two action :\r
+\r
+  1. if (AutoDefault) will add default for question to support all kinds of defaults.\r
+  2. if (CheckDefault) will generate an error to tell user the question misses some default value.\r
+\r
+  We assume that the two options can not be TRUE at same time.\r
+  If they are TRUE at same time, only do the action corresponding to AutoDefault option.\r
+\r
+  @param  AutoDefault          Add default for question if needed\r
+  @param  CheckDefault         Check the default info, if missing default, generates an error.\r
+\r
+**/\r
+VOID\r
+CIfrRecordInfoDB::IfrCheckAddDefaultRecord (\r
+  BOOLEAN  AutoDefault,\r
+  BOOLEAN  CheckDefault\r
+  )\r
+{\r
+  SIfrRecord            *pNode;\r
+  SIfrRecord            *pTailNode;\r
+  SIfrRecord            *pStartAdjustNode;\r
+  EFI_IFR_OP_HEADER     *pOpHead;\r
+  QuestionDefaultRecord  QuestionDefaultInfo;\r
+  UINT8                  MissingDefaultCount;\r
+  CHAR8                  Msg[MAX_STRING_LEN] = {0, };\r
+\r
+  pNode               = mIfrRecordListHead;\r
+\r
+  //\r
+  // Record the number and default id of all defaultstore opcode.\r
+  //\r
+  IfrGetDefaultStoreInfo ();\r
+\r
+  while (pNode != NULL) {\r
+    pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;\r
+    //\r
+    // Check whether is question opcode.\r
+    //\r
+    if (CheckQuestionOpCode (pOpHead->OpCode)) {\r
+      //\r
+      // Initialize some local variables here, because they vary with question.\r
+      // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.\r
+      //\r
+      memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord));\r
+      pTailNode = mIfrRecordListTail;\r
+      //\r
+      // Get the QuestionDefaultInfo for current question.\r
+      //\r
+      IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo);\r
+\r
+      if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) {\r
+        if (AutoDefault) {\r
+          //\r
+          // Create default for question which misses default.\r
+          //\r
+          IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo);\r
+\r
+          //\r
+          // Adjust the buffer content.\r
+          // pStartAdjustNode->mIfrBinBuf points to the insert position.\r
+          // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.\r
+          //\r
+          pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset);\r
+          gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE);\r
+\r
+          //\r
+          // Update the record info.\r
+          //\r
+          IfrUpdateRecordInfoForDynamicOpcode (TRUE);\r
+        } else if (CheckDefault) {\r
+          //\r
+          // Generate an error for question which misses default.\r
+          //\r
+          MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber;\r
+          sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode);\r
+          gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg);\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // parse next opcode.\r
+    //\r
+    pNode = pNode->mNext;\r
+  }\r
+}\r
+\r
 CIfrRecordInfoDB gCIfrRecordInfoDB;\r
 \r
 VOID\r