Home | History | Annotate | Download | only in VfrCompile
      1 /** @file
      2 
      3   The definition of CFormPkg's member function
      4 
      5 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "stdio.h"
     17 #include "VfrFormPkg.h"
     18 
     19 /*
     20  * The definition of CFormPkg's member function
     21  */
     22 
     23 SPendingAssign::SPendingAssign (
     24   IN CHAR8  *Key,
     25   IN VOID   *Addr,
     26   IN UINT32 Len,
     27   IN UINT32 LineNo,
     28   IN CONST CHAR8  *Msg
     29   )
     30 {
     31   mKey    = NULL;
     32   mAddr   = Addr;
     33   mLen    = Len;
     34   mFlag   = PENDING;
     35   mLineNo = LineNo;
     36   mMsg    = NULL;
     37   mNext   = NULL;
     38   if (Key != NULL) {
     39     mKey = new CHAR8[strlen (Key) + 1];
     40     if (mKey != NULL) {
     41       strcpy (mKey, Key);
     42     }
     43   }
     44 
     45   if (Msg != NULL) {
     46     mMsg = new CHAR8[strlen (Msg) + 1];
     47     if (mMsg != NULL) {
     48       strcpy (mMsg, Msg);
     49     }
     50   }
     51 }
     52 
     53 SPendingAssign::~SPendingAssign (
     54   VOID
     55   )
     56 {
     57   if (mKey != NULL) {
     58     delete mKey;
     59   }
     60   mAddr   = NULL;
     61   mLen    = 0;
     62   mLineNo = 0;
     63   if (mMsg != NULL) {
     64     delete mMsg;
     65   }
     66   mNext   = NULL;
     67 }
     68 
     69 VOID
     70 SPendingAssign::SetAddrAndLen (
     71   IN VOID   *Addr,
     72   IN UINT32 LineNo
     73   )
     74 {
     75   mAddr   = Addr;
     76   mLineNo = LineNo;
     77 }
     78 
     79 VOID
     80 SPendingAssign::AssignValue (
     81   IN VOID   *Addr,
     82   IN UINT32 Len
     83   )
     84 {
     85   memmove (mAddr, Addr, (mLen < Len ? mLen : Len));
     86   mFlag = ASSIGNED;
     87 }
     88 
     89 CHAR8 *
     90 SPendingAssign::GetKey (
     91   VOID
     92   )
     93 {
     94   return mKey;
     95 }
     96 
     97 CFormPkg::CFormPkg (
     98   IN UINT32 BufferSize
     99   )
    100 {
    101   CHAR8       *BufferStart;
    102   CHAR8       *BufferEnd;
    103   SBufferNode *Node;
    104 
    105   mPkgLength           = 0;
    106   mBufferNodeQueueHead = NULL;
    107   mCurrBufferNode      = NULL;
    108 
    109   Node = new SBufferNode;
    110   if (Node == NULL) {
    111     return ;
    112   }
    113   BufferStart = new CHAR8[BufferSize];
    114   if (BufferStart == NULL) {
    115     return;
    116   }
    117   BufferEnd   = BufferStart + BufferSize;
    118 
    119   memset (BufferStart, 0, BufferSize);
    120   Node->mBufferStart   = BufferStart;
    121   Node->mBufferEnd     = BufferEnd;
    122   Node->mBufferFree    = BufferStart;
    123   Node->mNext          = NULL;
    124 
    125   mBufferSize          = BufferSize;
    126   mBufferNodeQueueHead = Node;
    127   mBufferNodeQueueTail = Node;
    128   mCurrBufferNode      = Node;
    129 }
    130 
    131 CFormPkg::~CFormPkg ()
    132 {
    133   SBufferNode    *pBNode;
    134   SPendingAssign *pPNode;
    135 
    136   while (mBufferNodeQueueHead != NULL) {
    137     pBNode = mBufferNodeQueueHead;
    138     mBufferNodeQueueHead = mBufferNodeQueueHead->mNext;
    139     if (pBNode->mBufferStart != NULL) {
    140       delete pBNode->mBufferStart;
    141       delete pBNode;
    142     }
    143   }
    144   mBufferNodeQueueTail = NULL;
    145   mCurrBufferNode      = NULL;
    146 
    147   while (PendingAssignList != NULL) {
    148     pPNode = PendingAssignList;
    149     PendingAssignList = PendingAssignList->mNext;
    150     delete pPNode;
    151   }
    152   PendingAssignList = NULL;
    153 }
    154 
    155 SBufferNode *
    156 CFormPkg::CreateNewNode (
    157   VOID
    158   )
    159 {
    160   SBufferNode *Node;
    161 
    162   Node = new SBufferNode;
    163   if (Node == NULL) {
    164     return NULL;
    165   }
    166 
    167   Node->mBufferStart = new CHAR8[mBufferSize];
    168   if (Node->mBufferStart == NULL) {
    169     delete Node;
    170     return NULL;
    171   } else {
    172     memset (Node->mBufferStart, 0, mBufferSize);
    173     Node->mBufferEnd  = Node->mBufferStart + mBufferSize;
    174     Node->mBufferFree = Node->mBufferStart;
    175     Node->mNext       = NULL;
    176   }
    177 
    178   return Node;
    179 }
    180 
    181 CHAR8 *
    182 CFormPkg::IfrBinBufferGet (
    183   IN UINT32 Len
    184   )
    185 {
    186   CHAR8       *BinBuffer = NULL;
    187   SBufferNode *Node      = NULL;
    188 
    189   if ((Len == 0) || (Len > mBufferSize)) {
    190     return NULL;
    191   }
    192 
    193   if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) {
    194     BinBuffer = mCurrBufferNode->mBufferFree;
    195     mCurrBufferNode->mBufferFree += Len;
    196   } else {
    197     Node = CreateNewNode ();
    198     if (Node == NULL) {
    199       return NULL;
    200     }
    201 
    202     if (mBufferNodeQueueTail == NULL) {
    203       mBufferNodeQueueHead = mBufferNodeQueueTail = Node;
    204     } else {
    205       mBufferNodeQueueTail->mNext = Node;
    206       mBufferNodeQueueTail = Node;
    207     }
    208     mCurrBufferNode = Node;
    209 
    210     //
    211     // Now try again.
    212     //
    213     BinBuffer = mCurrBufferNode->mBufferFree;
    214     mCurrBufferNode->mBufferFree += Len;
    215   }
    216 
    217   mPkgLength += Len;
    218 
    219   return BinBuffer;
    220 }
    221 
    222 inline
    223 UINT32
    224 CFormPkg::GetPkgLength (
    225   VOID
    226   )
    227 {
    228   return mPkgLength;
    229 }
    230 
    231 VOID
    232 CFormPkg::Open (
    233   VOID
    234   )
    235 {
    236   mReadBufferNode   = mBufferNodeQueueHead;
    237   mReadBufferOffset = 0;
    238 }
    239 
    240 VOID
    241 CFormPkg::Close (
    242   VOID
    243   )
    244 {
    245   mReadBufferNode   = NULL;
    246   mReadBufferOffset = 0;
    247 }
    248 
    249 UINT32
    250 CFormPkg::Read (
    251   IN CHAR8     *Buffer,
    252   IN UINT32    Size
    253   )
    254 {
    255   UINT32       Index;
    256 
    257   if ((Size == 0) || (Buffer == NULL)) {
    258     return 0;
    259   }
    260 
    261   if (mReadBufferNode == NULL) {
    262     return 0;
    263   }
    264 
    265   for (Index = 0; Index < Size; Index++) {
    266     if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) {
    267       Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];
    268     } else {
    269       if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) {
    270         return Index;
    271       } else {
    272         mReadBufferOffset = 0;
    273         Index --;
    274       }
    275     }
    276   }
    277 
    278   return Size;
    279 }
    280 
    281 EFI_VFR_RETURN_CODE
    282 CFormPkg::BuildPkgHdr (
    283   OUT EFI_HII_PACKAGE_HEADER **PkgHdr
    284   )
    285 {
    286   if (PkgHdr == NULL) {
    287     return VFR_RETURN_FATAL_ERROR;
    288   }
    289 
    290   if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) {
    291     return VFR_RETURN_OUT_FOR_RESOURCES;
    292   }
    293 
    294   (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM;
    295   (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER);
    296 
    297   return VFR_RETURN_SUCCESS;
    298 }
    299 
    300 EFI_VFR_RETURN_CODE
    301 CFormPkg::BuildPkg (
    302   OUT PACKAGE_DATA &TBuffer
    303   )
    304 {
    305 
    306   CHAR8  *Temp;
    307   UINT32 Size;
    308   CHAR8  Buffer[1024];
    309 
    310   if (TBuffer.Buffer != NULL) {
    311     delete TBuffer.Buffer;
    312   }
    313 
    314   TBuffer.Size = mPkgLength;
    315   TBuffer.Buffer = NULL;
    316   if (TBuffer.Size != 0) {
    317     TBuffer.Buffer = new CHAR8[TBuffer.Size];
    318   } else {
    319     return VFR_RETURN_SUCCESS;
    320   }
    321 
    322   Temp = TBuffer.Buffer;
    323   Open ();
    324   while ((Size = Read (Buffer, 1024)) != 0) {
    325     memcpy (Temp, Buffer, Size);
    326     Temp += Size;
    327   }
    328   Close ();
    329   return VFR_RETURN_SUCCESS;
    330 }
    331 
    332 
    333 EFI_VFR_RETURN_CODE
    334 CFormPkg::BuildPkg (
    335   IN FILE  *Output,
    336   IN PACKAGE_DATA *PkgData
    337   )
    338 {
    339   EFI_VFR_RETURN_CODE     Ret;
    340   CHAR8                   Buffer[1024];
    341   UINT32                  Size;
    342   EFI_HII_PACKAGE_HEADER  *PkgHdr;
    343 
    344   if (Output == NULL) {
    345     return VFR_RETURN_FATAL_ERROR;
    346   }
    347 
    348   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
    349     return Ret;
    350   }
    351   fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);
    352   delete PkgHdr;
    353 
    354   if (PkgData == NULL) {
    355     Open ();
    356     while ((Size = Read (Buffer, 1024)) != 0) {
    357       fwrite (Buffer, Size, 1, Output);
    358     }
    359     Close ();
    360   } else {
    361     fwrite (PkgData->Buffer, PkgData->Size, 1, Output);
    362   }
    363 
    364   return VFR_RETURN_SUCCESS;
    365 }
    366 
    367 VOID
    368 CFormPkg::_WRITE_PKG_LINE (
    369   IN FILE         *pFile,
    370   IN UINT32       LineBytes,
    371   IN CONST CHAR8  *LineHeader,
    372   IN CHAR8        *BlkBuf,
    373   IN UINT32       BlkSize
    374   )
    375 {
    376   UINT32    Index;
    377 
    378   if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
    379     return;
    380   }
    381 
    382   for (Index = 0; Index < BlkSize; Index++) {
    383     if ((Index % LineBytes) == 0) {
    384       fprintf (pFile, "\n%s", LineHeader);
    385     }
    386     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
    387   }
    388 }
    389 
    390 VOID
    391 CFormPkg::_WRITE_PKG_END (
    392   IN FILE         *pFile,
    393   IN UINT32       LineBytes,
    394   IN CONST CHAR8  *LineHeader,
    395   IN CHAR8        *BlkBuf,
    396   IN UINT32       BlkSize
    397   )
    398 {
    399   UINT32    Index;
    400 
    401   if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
    402     return;
    403   }
    404 
    405   for (Index = 0; Index < BlkSize - 1; Index++) {
    406     if ((Index % LineBytes) == 0) {
    407       fprintf (pFile, "\n%s", LineHeader);
    408     }
    409     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
    410   }
    411 
    412   if ((Index % LineBytes) == 0) {
    413     fprintf (pFile, "\n%s", LineHeader);
    414   }
    415   fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);
    416 }
    417 
    418 #define BYTES_PRE_LINE 0x10
    419 UINT32   gAdjustOpcodeOffset = 0;
    420 BOOLEAN  gNeedAdjustOpcode   = FALSE;
    421 UINT32   gAdjustOpcodeLen    = 0;
    422 
    423 EFI_VFR_RETURN_CODE
    424 CFormPkg::GenCFile (
    425   IN CHAR8 *BaseName,
    426   IN FILE *pFile,
    427   IN PACKAGE_DATA *PkgData
    428   )
    429 {
    430   EFI_VFR_RETURN_CODE          Ret;
    431   CHAR8                        Buffer[BYTES_PRE_LINE * 8];
    432   EFI_HII_PACKAGE_HEADER       *PkgHdr;
    433   UINT32                       PkgLength  = 0;
    434   UINT32                       ReadSize   = 0;
    435 
    436   if ((BaseName == NULL) || (pFile == NULL)) {
    437     return VFR_RETURN_FATAL_ERROR;
    438   }
    439 
    440   fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);
    441 
    442   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
    443     return Ret;
    444   }
    445 
    446   //
    447   // For framework vfr file, the extension framework header will be added.
    448   //
    449   if (VfrCompatibleMode) {
    450 	  fprintf (pFile, "  // FRAMEWORK PACKAGE HEADER Length\n");
    451 	  PkgLength = PkgHdr->Length + sizeof (UINT32) + 2;
    452 	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));
    453 	  fprintf (pFile, "\n\n  // FRAMEWORK PACKAGE HEADER Type\n");
    454 	  PkgLength = 3;
    455 	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT16));
    456 	} else {
    457 	  fprintf (pFile, "  // ARRAY LENGTH\n");
    458 	  PkgLength = PkgHdr->Length + sizeof (UINT32);
    459 	  _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));
    460 	}
    461 
    462   fprintf (pFile, "\n\n  // PACKAGE HEADER\n");
    463   _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));
    464   PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);
    465 
    466   fprintf (pFile, "\n\n  // PACKAGE DATA\n");
    467 
    468   if (PkgData == NULL) {
    469     Open ();
    470     while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {
    471       PkgLength += ReadSize;
    472       if (PkgLength < PkgHdr->Length) {
    473         _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
    474       } else {
    475         _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
    476       }
    477     }
    478     Close ();
    479   } else {
    480     if (PkgData->Size % BYTES_PRE_LINE != 0) {
    481       PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE);
    482       _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
    483       _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE);
    484     } else {
    485       PkgLength = PkgData->Size - BYTES_PRE_LINE;
    486       _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
    487       _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE);
    488     }
    489   }
    490 
    491   delete PkgHdr;
    492   fprintf (pFile, "\n};\n");
    493 
    494   return VFR_RETURN_SUCCESS;
    495 }
    496 
    497 EFI_VFR_RETURN_CODE
    498 CFormPkg::AssignPending (
    499   IN CHAR8  *Key,
    500   IN VOID   *ValAddr,
    501   IN UINT32 ValLen,
    502   IN UINT32 LineNo,
    503   IN CONST CHAR8  *Msg
    504   )
    505 {
    506   SPendingAssign *pNew;
    507 
    508   pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);
    509   if (pNew == NULL) {
    510     return VFR_RETURN_OUT_FOR_RESOURCES;
    511   }
    512 
    513   pNew->mNext       = PendingAssignList;
    514   PendingAssignList = pNew;
    515   return VFR_RETURN_SUCCESS;
    516 }
    517 
    518 VOID
    519 CFormPkg::DoPendingAssign (
    520   IN CHAR8  *Key,
    521   IN VOID   *ValAddr,
    522   IN UINT32 ValLen
    523   )
    524 {
    525   SPendingAssign *pNode;
    526 
    527   if ((Key == NULL) || (ValAddr == NULL)) {
    528     return;
    529   }
    530 
    531   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
    532     if (strcmp (pNode->mKey, Key) == 0) {
    533       pNode->AssignValue (ValAddr, ValLen);
    534     }
    535   }
    536 }
    537 
    538 bool
    539 CFormPkg::HavePendingUnassigned (
    540   VOID
    541   )
    542 {
    543   SPendingAssign *pNode;
    544 
    545   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
    546     if (pNode->mFlag == PENDING) {
    547       return TRUE;
    548     }
    549   }
    550 
    551   return FALSE;
    552 }
    553 
    554 VOID
    555 CFormPkg::PendingAssignPrintAll (
    556   VOID
    557   )
    558 {
    559   SPendingAssign *pNode;
    560 
    561   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
    562     if (pNode->mFlag == PENDING) {
    563       gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);
    564     }
    565   }
    566 }
    567 
    568 SBufferNode *
    569 CFormPkg::GetBinBufferNodeForAddr (
    570   IN CHAR8              *BinBuffAddr
    571   )
    572 {
    573   SBufferNode *TmpNode;
    574 
    575   TmpNode = mBufferNodeQueueHead;
    576 
    577   while (TmpNode != NULL) {
    578     if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) {
    579       return TmpNode;
    580     }
    581 
    582     TmpNode = TmpNode->mNext;
    583   }
    584 
    585   return NULL;
    586 }
    587 
    588 SBufferNode *
    589 CFormPkg::GetNodeBefore(
    590   IN SBufferNode *CurrentNode
    591   )
    592 {
    593   SBufferNode *FirstNode   = mBufferNodeQueueHead;
    594   SBufferNode *LastNode    = mBufferNodeQueueHead;
    595 
    596   while (FirstNode != NULL) {
    597     if (FirstNode == CurrentNode) {
    598       break;
    599     }
    600 
    601     LastNode    = FirstNode;
    602     FirstNode   = FirstNode->mNext;
    603   }
    604 
    605   if (FirstNode == NULL) {
    606     LastNode = NULL;
    607   }
    608 
    609   return LastNode;
    610 }
    611 
    612 EFI_VFR_RETURN_CODE
    613 CFormPkg::InsertNodeBefore(
    614   IN SBufferNode *CurrentNode,
    615   IN SBufferNode *NewNode
    616   )
    617 {
    618   SBufferNode *LastNode = GetNodeBefore (CurrentNode);
    619 
    620   if (LastNode == NULL) {
    621     return VFR_RETURN_MISMATCHED;
    622   }
    623 
    624   NewNode->mNext = LastNode->mNext;
    625   LastNode->mNext = NewNode;
    626 
    627   return VFR_RETURN_SUCCESS;
    628 }
    629 
    630 CHAR8 *
    631 CFormPkg::GetBufAddrBaseOnOffset (
    632   IN UINT32      Offset
    633   )
    634 {
    635   SBufferNode *TmpNode;
    636   UINT32      TotalBufLen;
    637   UINT32      CurrentBufLen;
    638 
    639   TotalBufLen = 0;
    640 
    641   for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) {
    642     CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart;
    643     if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) {
    644       return TmpNode->mBufferStart + (Offset - TotalBufLen);
    645     }
    646 
    647     TotalBufLen += CurrentBufLen;
    648   }
    649 
    650   return NULL;
    651 }
    652 
    653 EFI_VFR_RETURN_CODE
    654 CFormPkg::AdjustDynamicInsertOpcode (
    655   IN CHAR8              *LastFormEndAddr,
    656   IN CHAR8              *InsertOpcodeAddr
    657   )
    658 {
    659   SBufferNode *LastFormEndNode;
    660   SBufferNode *InsertOpcodeNode;
    661   SBufferNode *NewRestoreNodeBegin;
    662   SBufferNode *NewRestoreNodeEnd;
    663   SBufferNode *NewLastEndNode;
    664   SBufferNode *TmpNode;
    665   UINT32      NeedRestoreCodeLen;
    666 
    667   NewRestoreNodeEnd = NULL;
    668 
    669   LastFormEndNode  = GetBinBufferNodeForAddr(LastFormEndAddr);
    670   InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);
    671 
    672   if (LastFormEndNode == InsertOpcodeNode) {
    673     //
    674     // Create New Node to save the restore opcode.
    675     //
    676     NeedRestoreCodeLen = InsertOpcodeAddr - LastFormEndAddr;
    677     gAdjustOpcodeLen   = NeedRestoreCodeLen;
    678     NewRestoreNodeBegin = CreateNewNode ();
    679     if (NewRestoreNodeBegin == NULL) {
    680       return VFR_RETURN_OUT_FOR_RESOURCES;
    681     }
    682     memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
    683     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
    684 
    685     //
    686     // Override the restore buffer data.
    687     //
    688     memmove (LastFormEndAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
    689     InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;
    690     memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);
    691   } else {
    692     //
    693     // Create New Node to save the restore opcode.
    694     //
    695     NeedRestoreCodeLen = LastFormEndNode->mBufferFree - LastFormEndAddr;
    696     gAdjustOpcodeLen   = NeedRestoreCodeLen;
    697     NewRestoreNodeBegin = CreateNewNode ();
    698     if (NewRestoreNodeBegin == NULL) {
    699       return VFR_RETURN_OUT_FOR_RESOURCES;
    700     }
    701     memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
    702     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
    703     //
    704     // Override the restore buffer data.
    705     //
    706     LastFormEndNode->mBufferFree -= NeedRestoreCodeLen;
    707     //
    708     // Link the restore data to new node.
    709     //
    710     NewRestoreNodeBegin->mNext = LastFormEndNode->mNext;
    711 
    712     //
    713     // Count the Adjust opcode len.
    714     //
    715     TmpNode = LastFormEndNode->mNext;
    716     while (TmpNode != InsertOpcodeNode) {
    717       gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;
    718       TmpNode = TmpNode->mNext;
    719     }
    720 
    721     //
    722     // Create New Node to save the last node of restore opcode.
    723     //
    724     NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
    725     gAdjustOpcodeLen  += NeedRestoreCodeLen;
    726     if (NeedRestoreCodeLen > 0) {
    727       NewRestoreNodeEnd = CreateNewNode ();
    728       if (NewRestoreNodeEnd == NULL) {
    729         return VFR_RETURN_OUT_FOR_RESOURCES;
    730       }
    731       memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen);
    732       NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen;
    733       //
    734       // Override the restore buffer data.
    735       //
    736       memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
    737       InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
    738 
    739       //
    740       // Insert the last restore data node.
    741       //
    742       TmpNode = GetNodeBefore (InsertOpcodeNode);
    743       if (TmpNode == LastFormEndNode) {
    744         NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;
    745       } else {
    746         TmpNode->mNext = NewRestoreNodeEnd;
    747       }
    748       //
    749       // Connect the dynamic opcode node to the node before last form end node.
    750       //
    751       LastFormEndNode->mNext = InsertOpcodeNode;
    752     }
    753   }
    754 
    755   if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
    756     //
    757     // End form set opcode all in the mBufferNodeQueueTail node.
    758     //
    759     NewLastEndNode = CreateNewNode ();
    760     if (NewLastEndNode == NULL) {
    761       return VFR_RETURN_OUT_FOR_RESOURCES;
    762     }
    763     NewLastEndNode->mBufferStart[0] = 0x29;
    764     NewLastEndNode->mBufferStart[1] = 0x02;
    765     NewLastEndNode->mBufferFree += 2;
    766 
    767     mBufferNodeQueueTail->mBufferFree -= 2;
    768 
    769     mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
    770     if (NewRestoreNodeEnd != NULL) {
    771       NewRestoreNodeEnd->mNext = NewLastEndNode;
    772     } else {
    773       NewRestoreNodeBegin->mNext = NewLastEndNode;
    774     }
    775 
    776     mBufferNodeQueueTail = NewLastEndNode;
    777   } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
    778     TmpNode = GetNodeBefore(mBufferNodeQueueTail);
    779     TmpNode->mNext = NewRestoreNodeBegin;
    780     if (NewRestoreNodeEnd != NULL) {
    781       NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
    782     } else {
    783       NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
    784     }
    785   }
    786 
    787   return VFR_RETURN_SUCCESS;
    788 }
    789 
    790 EFI_VFR_RETURN_CODE
    791 CFormPkg::DeclarePendingQuestion (
    792   IN CVfrVarDataTypeDB   &lCVfrVarDataTypeDB,
    793   IN CVfrDataStorage     &lCVfrDataStorage,
    794   IN CVfrQuestionDB      &lCVfrQuestionDB,
    795   IN EFI_GUID            *LocalFormSetGuid,
    796   IN UINT32              LineNo,
    797   OUT CHAR8              **InsertOpcodeAddr
    798   )
    799 {
    800   SPendingAssign *pNode;
    801   CHAR8          *VarStr;
    802   UINT32         ArrayIdx;
    803   CHAR8          FName[MAX_NAME_LEN];
    804   CHAR8          *SName;
    805   CHAR8          *NewStr;
    806   UINT32         ShrinkSize;
    807   EFI_VFR_RETURN_CODE  ReturnCode;
    808   EFI_VFR_VARSTORE_TYPE VarStoreType  = EFI_VFR_VARSTORE_INVALID;
    809   EFI_VARSTORE_ID       VarStoreId    = EFI_VARSTORE_ID_INVALID;
    810 
    811   //
    812   // Declare all questions as Numeric in DisableIf True
    813   //
    814   // DisableIf
    815   CIfrDisableIf DIObj;
    816   DIObj.SetLineNo (LineNo);
    817   *InsertOpcodeAddr = DIObj.GetObjBinAddr ();
    818 
    819   //TrueOpcode
    820   CIfrTrue TObj (LineNo);
    821 
    822   // Declare Numeric qeustion for each undefined question.
    823   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
    824     if (pNode->mFlag == PENDING) {
    825       CIfrNumeric CNObj;
    826       EFI_VARSTORE_INFO Info;
    827       EFI_QUESTION_ID   QId   = EFI_QUESTION_ID_INVALID;
    828 
    829       CNObj.SetLineNo (LineNo);
    830       CNObj.SetPrompt (0x0);
    831       CNObj.SetHelp (0x0);
    832 
    833       //
    834       // Register this question, assume it is normal question, not date or time question
    835       //
    836       VarStr = pNode->mKey;
    837       ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId);
    838       if (ReturnCode != VFR_RETURN_SUCCESS) {
    839         gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
    840         return ReturnCode;
    841       }
    842 
    843 #ifdef VFREXP_DEBUG
    844       printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId);
    845 #endif
    846       //
    847       // Get Question Info, framework vfr VarName == StructName
    848       //
    849       ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx);
    850       if (ReturnCode != VFR_RETURN_SUCCESS) {
    851         gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable");
    852         return ReturnCode;
    853       }
    854       //
    855       // Get VarStoreType
    856       //
    857       ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId);
    858       if (ReturnCode != VFR_RETURN_SUCCESS) {
    859         gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");
    860         return ReturnCode;
    861       }
    862       VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId);
    863 
    864       if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) {
    865         ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx);
    866       } else {
    867         if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
    868           ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);
    869         } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) {
    870           VarStr = pNode->mKey;
    871           //convert VarStr with store name to VarStr with structure name
    872           ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName);
    873           if (ReturnCode == VFR_RETURN_SUCCESS) {
    874             NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1];
    875             NewStr[0] = '\0';
    876             strcpy (NewStr, SName);
    877             strcat (NewStr, VarStr + strlen (FName));
    878             ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize);
    879             delete NewStr;
    880           }
    881         } else {
    882           ReturnCode = VFR_RETURN_UNSUPPORTED;
    883         }
    884       }
    885       if (ReturnCode != VFR_RETURN_SUCCESS) {
    886         gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
    887         return ReturnCode;
    888       }
    889 
    890       CNObj.SetQuestionId (QId);
    891       CNObj.SetVarStoreInfo (&Info);
    892       //
    893       // Numeric doesn't support BOOLEAN data type.
    894       // BOOLEAN type has the same data size to UINT8.
    895       //
    896       if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
    897         Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
    898       }
    899       CNObj.SetFlags (0, Info.mVarType);
    900       //
    901       // Use maximum value not to limit the vaild value for the undefined question.
    902       //
    903       switch (Info.mVarType) {
    904       case EFI_IFR_TYPE_NUM_SIZE_64:
    905         CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
    906         ShrinkSize = 0;
    907         break;
    908       case EFI_IFR_TYPE_NUM_SIZE_32:
    909         CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
    910         ShrinkSize = 12;
    911         break;
    912       case EFI_IFR_TYPE_NUM_SIZE_16:
    913         CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
    914         ShrinkSize = 18;
    915         break;
    916       case EFI_IFR_TYPE_NUM_SIZE_8:
    917         CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
    918         ShrinkSize = 21;
    919         break;
    920       default:
    921         break;
    922       }
    923       CNObj.ShrinkBinSize (ShrinkSize);
    924 
    925       //
    926       // For undefined Efi VarStore type question
    927       // Append the extended guided opcode to contain VarName
    928       //
    929       if (VarStoreType == EFI_VFR_VARSTORE_EFI || VfrCompatibleMode) {
    930         CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName);
    931         CVNObj.SetLineNo (LineNo);
    932       }
    933 
    934       //
    935       // End for Numeric
    936       //
    937       CIfrEnd CEObj;
    938       CEObj.SetLineNo (LineNo);
    939     }
    940   }
    941 
    942   //
    943   // End for DisableIf
    944   //
    945   CIfrEnd SEObj;
    946   SEObj.SetLineNo (LineNo);
    947 
    948   return VFR_RETURN_SUCCESS;
    949 }
    950 
    951 CFormPkg gCFormPkg;
    952 
    953 SIfrRecord::SIfrRecord (
    954   VOID
    955   )
    956 {
    957   mIfrBinBuf = NULL;
    958   mBinBufLen = 0;
    959   mLineNo    = 0xFFFFFFFF;
    960   mOffset    = 0xFFFFFFFF;
    961   mNext      = NULL;
    962 }
    963 
    964 SIfrRecord::~SIfrRecord (
    965   VOID
    966   )
    967 {
    968   if (mIfrBinBuf != NULL) {
    969     //delete mIfrBinBuf;
    970     mIfrBinBuf = NULL;
    971   }
    972   mLineNo      = 0xFFFFFFFF;
    973   mOffset      = 0xFFFFFFFF;
    974   mBinBufLen   = 0;
    975   mNext        = NULL;
    976 }
    977 
    978 CIfrRecordInfoDB::CIfrRecordInfoDB (
    979   VOID
    980   )
    981 {
    982   mSwitch            = TRUE;
    983   mRecordCount       = EFI_IFR_RECORDINFO_IDX_START;
    984   mIfrRecordListHead = NULL;
    985   mIfrRecordListTail = NULL;
    986 }
    987 
    988 CIfrRecordInfoDB::~CIfrRecordInfoDB (
    989   VOID
    990   )
    991 {
    992   SIfrRecord *pNode;
    993 
    994   while (mIfrRecordListHead != NULL) {
    995     pNode = mIfrRecordListHead;
    996     mIfrRecordListHead = mIfrRecordListHead->mNext;
    997     delete pNode;
    998   }
    999 }
   1000 
   1001 SIfrRecord *
   1002 CIfrRecordInfoDB::GetRecordInfoFromIdx (
   1003   IN UINT32 RecordIdx
   1004   )
   1005 {
   1006   UINT32     Idx;
   1007   SIfrRecord *pNode = NULL;
   1008 
   1009   if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {
   1010     return NULL;
   1011   }
   1012 
   1013   for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead;
   1014        (Idx != RecordIdx) && (pNode != NULL);
   1015        Idx++, pNode = pNode->mNext)
   1016   ;
   1017 
   1018   return pNode;
   1019 }
   1020 
   1021 UINT32
   1022 CIfrRecordInfoDB::IfrRecordRegister (
   1023   IN UINT32 LineNo,
   1024   IN CHAR8  *IfrBinBuf,
   1025   IN UINT8  BinBufLen,
   1026   IN UINT32 Offset
   1027   )
   1028 {
   1029   SIfrRecord *pNew;
   1030 
   1031   if (mSwitch == FALSE) {
   1032     return EFI_IFR_RECORDINFO_IDX_INVALUD;
   1033   }
   1034 
   1035   if ((pNew = new SIfrRecord) == NULL) {
   1036     return EFI_IFR_RECORDINFO_IDX_INVALUD;
   1037   }
   1038 
   1039   if (mIfrRecordListHead == NULL) {
   1040     mIfrRecordListHead = pNew;
   1041     mIfrRecordListTail = pNew;
   1042   } else {
   1043     mIfrRecordListTail->mNext = pNew;
   1044     mIfrRecordListTail = pNew;
   1045   }
   1046   mRecordCount++;
   1047 
   1048   return mRecordCount;
   1049 }
   1050 
   1051 VOID
   1052 CIfrRecordInfoDB::IfrRecordInfoUpdate (
   1053   IN UINT32 RecordIdx,
   1054   IN UINT32 LineNo,
   1055   IN CHAR8  *BinBuf,
   1056   IN UINT8  BinBufLen,
   1057   IN UINT32 Offset
   1058   )
   1059 {
   1060   SIfrRecord *pNode;
   1061   SIfrRecord *Prev;
   1062 
   1063   if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {
   1064     return;
   1065   }
   1066 
   1067   if (LineNo == 0) {
   1068     //
   1069     // Line number is not specified explicitly, try to use line number of previous opcode
   1070     //
   1071     Prev = GetRecordInfoFromIdx (RecordIdx - 1);
   1072     if (Prev != NULL) {
   1073       LineNo = Prev->mLineNo;
   1074     }
   1075   }
   1076 
   1077   pNode->mLineNo    = LineNo;
   1078   pNode->mOffset    = Offset;
   1079   pNode->mBinBufLen = BinBufLen;
   1080   pNode->mIfrBinBuf = BinBuf;
   1081 
   1082 }
   1083 
   1084 VOID
   1085 CIfrRecordInfoDB::IfrRecordOutput (
   1086   OUT PACKAGE_DATA &TBuffer
   1087   )
   1088 {
   1089   CHAR8      *Temp;
   1090   SIfrRecord *pNode;
   1091 
   1092   if (TBuffer.Buffer != NULL) {
   1093     delete TBuffer.Buffer;
   1094   }
   1095 
   1096   TBuffer.Size = 0;
   1097   TBuffer.Buffer = NULL;
   1098 
   1099 
   1100   if (mSwitch == FALSE) {
   1101     return;
   1102   }
   1103 
   1104   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
   1105     TBuffer.Size += pNode->mBinBufLen;
   1106   }
   1107 
   1108   if (TBuffer.Size != 0) {
   1109     TBuffer.Buffer = new CHAR8[TBuffer.Size];
   1110   } else {
   1111     return;
   1112   }
   1113 
   1114   Temp = TBuffer.Buffer;
   1115 
   1116   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
   1117     if (pNode->mIfrBinBuf != NULL) {
   1118       memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen);
   1119       Temp += pNode->mBinBufLen;
   1120     }
   1121   }
   1122 
   1123   return;
   1124 }
   1125 
   1126 VOID
   1127 CIfrRecordInfoDB::IfrRecordOutput (
   1128   IN FILE   *File,
   1129   IN UINT32 LineNo
   1130   )
   1131 {
   1132   SIfrRecord *pNode;
   1133   UINT8      Index;
   1134   UINT32     TotalSize;
   1135 
   1136   if (mSwitch == FALSE) {
   1137     return;
   1138   }
   1139 
   1140   if (File == NULL) {
   1141     return;
   1142   }
   1143 
   1144   TotalSize = 0;
   1145 
   1146   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
   1147     if (pNode->mLineNo == LineNo || LineNo == 0) {
   1148       fprintf (File, ">%08X: ", pNode->mOffset);
   1149       TotalSize += pNode->mBinBufLen;
   1150       if (pNode->mIfrBinBuf != NULL) {
   1151         for (Index = 0; Index < pNode->mBinBufLen; Index++) {
   1152           fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));
   1153         }
   1154       }
   1155       fprintf (File, "\n");
   1156     }
   1157   }
   1158 
   1159   if (LineNo == 0) {
   1160     fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize);
   1161   }
   1162 }
   1163 
   1164 //
   1165 // for framework vfr file
   1166 // adjust opcode sequence for uefi IFR format
   1167 // adjust inconsistent and varstore into the right position.
   1168 //
   1169 BOOLEAN
   1170 CIfrRecordInfoDB::CheckQuestionOpCode (
   1171   IN UINT8 OpCode
   1172   )
   1173 {
   1174   switch (OpCode) {
   1175   case EFI_IFR_CHECKBOX_OP:
   1176   case EFI_IFR_NUMERIC_OP:
   1177   case EFI_IFR_PASSWORD_OP:
   1178   case EFI_IFR_ONE_OF_OP:
   1179   case EFI_IFR_ACTION_OP:
   1180   case EFI_IFR_STRING_OP:
   1181   case EFI_IFR_DATE_OP:
   1182   case EFI_IFR_TIME_OP:
   1183   case EFI_IFR_ORDERED_LIST_OP:
   1184     return TRUE;
   1185   default:
   1186     return FALSE;
   1187   }
   1188 }
   1189 
   1190 BOOLEAN
   1191 CIfrRecordInfoDB::CheckIdOpCode (
   1192   IN UINT8 OpCode
   1193   )
   1194 {
   1195   switch (OpCode) {
   1196   case EFI_IFR_EQ_ID_VAL_OP:
   1197   case EFI_IFR_EQ_ID_ID_OP:
   1198   case EFI_IFR_EQ_ID_VAL_LIST_OP:
   1199   case EFI_IFR_QUESTION_REF1_OP:
   1200     return TRUE;
   1201   default:
   1202     return FALSE;
   1203   }
   1204 }
   1205 
   1206 EFI_QUESTION_ID
   1207 CIfrRecordInfoDB::GetOpcodeQuestionId (
   1208   IN EFI_IFR_OP_HEADER *OpHead
   1209   )
   1210 {
   1211   EFI_IFR_QUESTION_HEADER *QuestionHead;
   1212 
   1213   QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1);
   1214 
   1215   return QuestionHead->QuestionId;
   1216 }
   1217 
   1218 SIfrRecord *
   1219 CIfrRecordInfoDB::GetRecordInfoFromOffset (
   1220   IN UINT32 Offset
   1221   )
   1222 {
   1223   SIfrRecord *pNode = NULL;
   1224 
   1225   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
   1226     if (pNode->mOffset == Offset) {
   1227       return pNode;
   1228     }
   1229   }
   1230 
   1231   return pNode;
   1232 }
   1233 
   1234 /*
   1235   Add just the op code position.
   1236 
   1237   From
   1238 
   1239   | form end opcode + end of if opcode for form ... + Dynamic opcode + form set end opcode |
   1240 
   1241   To
   1242 
   1243   | Dynamic opcode + form end opcode + end of if opcode for form ... + form set end opcode |
   1244 
   1245 */
   1246 BOOLEAN
   1247 CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (
   1248   VOID
   1249   )
   1250 {
   1251   UINT32             OpcodeOffset;
   1252   SIfrRecord         *pNode, *pPreNode;
   1253   SIfrRecord         *pStartNode, *pNodeBeforeStart;
   1254   SIfrRecord         *pEndNode;
   1255 
   1256   pStartNode = NULL;
   1257   pEndNode   = NULL;
   1258   OpcodeOffset = 0;
   1259 
   1260   //
   1261   // Base on the offset info to get the node.
   1262   //
   1263   for (pNode = mIfrRecordListHead; pNode->mNext != NULL; pPreNode = pNode,pNode = pNode->mNext) {
   1264     if (OpcodeOffset == gAdjustOpcodeOffset) {
   1265       pStartNode       = pNode;
   1266       pNodeBeforeStart = pPreNode;
   1267     } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {
   1268       pEndNode = pPreNode;
   1269     }
   1270 
   1271     OpcodeOffset += pNode->mBinBufLen;
   1272   }
   1273 
   1274   //
   1275   // Check the value.
   1276   //
   1277   if (pEndNode == NULL || pStartNode == NULL) {
   1278     return FALSE;
   1279   }
   1280 
   1281   //
   1282   // Adjust the node. pPreNode save the Node before mIfrRecordListTail
   1283   //
   1284   pNodeBeforeStart->mNext = pEndNode->mNext;
   1285   pPreNode->mNext = pStartNode;
   1286   pEndNode->mNext = mIfrRecordListTail;
   1287 
   1288   return TRUE;
   1289 }
   1290 
   1291 VOID
   1292 CIfrRecordInfoDB::IfrAdjustOffsetForRecord (
   1293   VOID
   1294   )
   1295 {
   1296   UINT32             OpcodeOffset;
   1297   SIfrRecord         *pNode;
   1298 
   1299   OpcodeOffset = 0;
   1300   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
   1301     pNode->mOffset = OpcodeOffset;
   1302     OpcodeOffset += pNode->mBinBufLen;
   1303   }
   1304 }
   1305 
   1306 EFI_VFR_RETURN_CODE
   1307 CIfrRecordInfoDB::IfrRecordAdjust (
   1308   VOID
   1309   )
   1310 {
   1311   SIfrRecord *pNode, *preNode;
   1312   SIfrRecord *uNode, *tNode;
   1313   EFI_IFR_OP_HEADER  *OpHead, *tOpHead;
   1314   EFI_QUESTION_ID    QuestionId;
   1315   UINT32             StackCount;
   1316   UINT32             QuestionScope;
   1317   UINT32             OpcodeOffset;
   1318   CHAR8              ErrorMsg[MAX_STRING_LEN] = {0, };
   1319   EFI_VFR_RETURN_CODE  Status;
   1320 
   1321   //
   1322   // Init local variable
   1323   //
   1324   Status = VFR_RETURN_SUCCESS;
   1325   pNode = mIfrRecordListHead;
   1326   preNode = pNode;
   1327   QuestionScope = 0;
   1328   while (pNode != NULL) {
   1329     OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
   1330 
   1331     //
   1332     // make sure the inconsistent opcode in question scope
   1333     //
   1334     if (QuestionScope > 0) {
   1335       QuestionScope += OpHead->Scope;
   1336       if (OpHead->OpCode == EFI_IFR_END_OP) {
   1337         QuestionScope --;
   1338       }
   1339     }
   1340 
   1341     if (CheckQuestionOpCode (OpHead->OpCode)) {
   1342       QuestionScope = 1;
   1343     }
   1344     //
   1345     // for the inconsistent opcode not in question scope, adjust it
   1346     //
   1347     if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) {
   1348       //
   1349       // for inconsistent opcode not in question scope
   1350       //
   1351 
   1352       //
   1353       // Count inconsistent opcode Scope
   1354       //
   1355       StackCount = OpHead->Scope;
   1356       QuestionId = EFI_QUESTION_ID_INVALID;
   1357       tNode = pNode;
   1358       while (tNode != NULL && StackCount > 0) {
   1359         tNode = tNode->mNext;
   1360         tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf;
   1361         //
   1362         // Calculate Scope Number
   1363         //
   1364         StackCount += tOpHead->Scope;
   1365         if (tOpHead->OpCode == EFI_IFR_END_OP) {
   1366           StackCount --;
   1367         }
   1368         //
   1369         // by IdEqual opcode to get QuestionId
   1370         //
   1371         if (QuestionId == EFI_QUESTION_ID_INVALID &&
   1372             CheckIdOpCode (tOpHead->OpCode)) {
   1373           QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1);
   1374         }
   1375       }
   1376       if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) {
   1377         //
   1378         // report error; not found
   1379         //
   1380         sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId);
   1381         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
   1382         Status = VFR_RETURN_MISMATCHED;
   1383         break;
   1384       }
   1385       //
   1386       // extract inconsistent opcode list
   1387       // pNode is Incosistent opcode, tNode is End Opcode
   1388       //
   1389 
   1390       //
   1391       // insert inconsistent opcode list into the right question scope by questionid
   1392       //
   1393       for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) {
   1394         tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf;
   1395         if (CheckQuestionOpCode (tOpHead->OpCode) &&
   1396             (QuestionId == GetOpcodeQuestionId (tOpHead))) {
   1397           break;
   1398         }
   1399       }
   1400       //
   1401       // insert inconsistent opcode list and check LATE_CHECK flag
   1402       //
   1403       if (uNode != NULL) {
   1404         if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) {
   1405           //
   1406           // if LATE_CHECK flag is set, change inconsistent to nosumbit
   1407           //
   1408           OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP;
   1409         }
   1410 
   1411         //
   1412         // skip the default storage for Date and Time
   1413         //
   1414         if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) {
   1415           uNode = uNode->mNext;
   1416         }
   1417 
   1418         preNode->mNext = tNode->mNext;
   1419         tNode->mNext = uNode->mNext;
   1420         uNode->mNext = pNode;
   1421         //
   1422         // reset pNode to head list, scan the whole list again.
   1423         //
   1424         pNode = mIfrRecordListHead;
   1425         preNode = pNode;
   1426         QuestionScope = 0;
   1427         continue;
   1428       } else {
   1429         //
   1430         // not found matched question id, report error
   1431         //
   1432         sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId);
   1433         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
   1434         Status = VFR_RETURN_MISMATCHED;
   1435         break;
   1436       }
   1437     } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP ||
   1438                OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) {
   1439       //
   1440       // for new added group of varstore opcode
   1441       //
   1442       tNode = pNode;
   1443       while (tNode->mNext != NULL) {
   1444         tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf;
   1445         if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP &&
   1446             tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) {
   1447           break;
   1448         }
   1449         tNode = tNode->mNext;
   1450       }
   1451 
   1452       if (tNode->mNext == NULL) {
   1453         //
   1454         // invalid IfrCode, IfrCode end by EndOpCode
   1455         //
   1456         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end");
   1457         Status = VFR_RETURN_MISMATCHED;
   1458         break;
   1459       }
   1460 
   1461       if (tOpHead->OpCode != EFI_IFR_END_OP) {
   1462           //
   1463           // not new added varstore, which are not needed to be adjust.
   1464           //
   1465           preNode = tNode;
   1466           pNode   = tNode->mNext;
   1467           continue;
   1468       } else {
   1469         //
   1470         // move new added varstore opcode to the position befor form opcode
   1471         // varstore opcode between pNode and tNode
   1472         //
   1473 
   1474         //
   1475         // search form opcode from begin
   1476         //
   1477         for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) {
   1478           tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf;
   1479           if (tOpHead->OpCode == EFI_IFR_FORM_OP) {
   1480             break;
   1481           }
   1482         }
   1483         //
   1484         // Insert varstore opcode beform form opcode if form opcode is found
   1485         //
   1486         if (uNode->mNext != NULL) {
   1487           preNode->mNext = tNode->mNext;
   1488           tNode->mNext = uNode->mNext;
   1489           uNode->mNext = pNode;
   1490           //
   1491           // reset pNode to head list, scan the whole list again.
   1492           //
   1493           pNode = mIfrRecordListHead;
   1494           preNode = pNode;
   1495           QuestionScope = 0;
   1496           continue;
   1497         } else {
   1498           //
   1499           // not found form, continue scan IfrRecord list
   1500           //
   1501           preNode = tNode;
   1502           pNode   = tNode->mNext;
   1503           continue;
   1504         }
   1505       }
   1506     }
   1507     //
   1508     // next node
   1509     //
   1510     preNode = pNode;
   1511     pNode = pNode->mNext;
   1512   }
   1513 
   1514   //
   1515   // Update Ifr Opcode Offset
   1516   //
   1517   if (Status == VFR_RETURN_SUCCESS) {
   1518     IfrAdjustOffsetForRecord ();
   1519   }
   1520   return Status;
   1521 }
   1522 
   1523 CIfrRecordInfoDB gCIfrRecordInfoDB;
   1524 
   1525 VOID
   1526 CIfrObj::_EMIT_PENDING_OBJ (
   1527   VOID
   1528   )
   1529 {
   1530   CHAR8  *ObjBinBuf = NULL;
   1531 
   1532   //
   1533   // do nothing
   1534   //
   1535   if (!mDelayEmit || !gCreateOp) {
   1536     return;
   1537   }
   1538 
   1539   mPkgOffset = gCFormPkg.GetPkgLength ();
   1540   //
   1541   // update data buffer to package data
   1542   //
   1543   ObjBinBuf  = gCFormPkg.IfrBinBufferGet (mObjBinLen);
   1544   if (ObjBinBuf != NULL) {
   1545     memmove (ObjBinBuf, mObjBinBuf, mObjBinLen);
   1546   }
   1547 
   1548   //
   1549   // update bin buffer to package data buffer
   1550   //
   1551   if (mObjBinBuf != NULL) {
   1552     delete mObjBinBuf;
   1553     mObjBinBuf = ObjBinBuf;
   1554   }
   1555 
   1556   mDelayEmit = FALSE;
   1557 }
   1558 
   1559 /*
   1560  * The definition of CIfrObj's member function
   1561  */
   1562 static struct {
   1563   UINT8  mSize;
   1564   UINT8  mScope;
   1565 } gOpcodeSizesScopeTable[] = {
   1566   { 0, 0 },                                    // EFI_IFR_INVALID - 0x00
   1567   { sizeof (EFI_IFR_FORM), 1 },                // EFI_IFR_FORM_OP
   1568   { sizeof (EFI_IFR_SUBTITLE), 1 },            // EFI_IFR_SUBTITLE_OP
   1569   { sizeof (EFI_IFR_TEXT), 0 },                // EFI_IFR_TEXT_OP
   1570   { sizeof (EFI_IFR_IMAGE), 0 },               // EFI_IFR_IMAGE_OP
   1571   { sizeof (EFI_IFR_ONE_OF), 1 },              // EFI_IFR_ONE_OF_OP - 0x05
   1572   { sizeof (EFI_IFR_CHECKBOX), 1},             // EFI_IFR_CHECKBOX_OP
   1573   { sizeof (EFI_IFR_NUMERIC), 1 },             // EFI_IFR_NUMERIC_OP
   1574   { sizeof (EFI_IFR_PASSWORD), 1 },            // EFI_IFR_PASSWORD_OP
   1575   { sizeof (EFI_IFR_ONE_OF_OPTION), 0 },       // EFI_IFR_ONE_OF_OPTION_OP
   1576   { sizeof (EFI_IFR_SUPPRESS_IF), 1 },         // EFI_IFR_SUPPRESS_IF - 0x0A
   1577   { sizeof (EFI_IFR_LOCKED), 0 },              // EFI_IFR_LOCKED_OP
   1578   { sizeof (EFI_IFR_ACTION), 1 },              // EFI_IFR_ACTION_OP
   1579   { sizeof (EFI_IFR_RESET_BUTTON), 1 },        // EFI_IFR_RESET_BUTTON_OP
   1580   { sizeof (EFI_IFR_FORM_SET), 1 },            // EFI_IFR_FORM_SET_OP -0xE
   1581   { sizeof (EFI_IFR_REF), 0 },                 // EFI_IFR_REF_OP
   1582   { sizeof (EFI_IFR_NO_SUBMIT_IF), 1},         // EFI_IFR_NO_SUBMIT_IF_OP -0x10
   1583   { sizeof (EFI_IFR_INCONSISTENT_IF), 1 },     // EFI_IFR_INCONSISTENT_IF_OP
   1584   { sizeof (EFI_IFR_EQ_ID_VAL), 0 },           // EFI_IFR_EQ_ID_VAL_OP
   1585   { sizeof (EFI_IFR_EQ_ID_ID), 0 },            // EFI_IFR_EQ_ID_ID_OP
   1586   { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 },      // EFI_IFR_EQ_ID_LIST_OP - 0x14
   1587   { sizeof (EFI_IFR_AND), 0 },                 // EFI_IFR_AND_OP
   1588   { sizeof (EFI_IFR_OR), 0 },                  // EFI_IFR_OR_OP
   1589   { sizeof (EFI_IFR_NOT), 0 },                 // EFI_IFR_NOT_OP
   1590   { sizeof (EFI_IFR_RULE), 1 },                // EFI_IFR_RULE_OP
   1591   { sizeof (EFI_IFR_GRAY_OUT_IF), 1 },         // EFI_IFR_GRAYOUT_IF_OP - 0x19
   1592   { sizeof (EFI_IFR_DATE), 1 },                // EFI_IFR_DATE_OP
   1593   { sizeof (EFI_IFR_TIME), 1 },                // EFI_IFR_TIME_OP
   1594   { sizeof (EFI_IFR_STRING), 1 },              // EFI_IFR_STRING_OP
   1595   { sizeof (EFI_IFR_REFRESH), 0 },             // EFI_IFR_REFRESH_OP
   1596   { sizeof (EFI_IFR_DISABLE_IF), 1 },          // EFI_IFR_DISABLE_IF_OP - 0x1E
   1597   { 0, 0 },                                    // 0x1F
   1598   { sizeof (EFI_IFR_TO_LOWER), 0 },            // EFI_IFR_TO_LOWER_OP - 0x20
   1599   { sizeof (EFI_IFR_TO_UPPER), 0 },            // EFI_IFR_TO_UPPER_OP - 0x21
   1600   { sizeof (EFI_IFR_MAP), 1 },                 // EFI_IFR_MAP - 0x22
   1601   { sizeof (EFI_IFR_ORDERED_LIST), 1 },        // EFI_IFR_ORDERED_LIST_OP - 0x23
   1602   { sizeof (EFI_IFR_VARSTORE), 0 },            // EFI_IFR_VARSTORE_OP
   1603   { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP
   1604   { sizeof (EFI_IFR_VARSTORE_EFI), 0 },        // EFI_IFR_VARSTORE_EFI_OP
   1605   { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 },     // EFI_IFR_VARSTORE_DEVICE_OP
   1606   { sizeof (EFI_IFR_VERSION), 0 },             // EFI_IFR_VERSION_OP - 0x28
   1607   { sizeof (EFI_IFR_END), 0 },                 // EFI_IFR_END_OP
   1608   { sizeof (EFI_IFR_MATCH), 0 },               // EFI_IFR_MATCH_OP - 0x2A
   1609   { sizeof (EFI_IFR_GET), 0 },                 // EFI_IFR_GET - 0x2B
   1610   { sizeof (EFI_IFR_SET), 0 },                 // EFI_IFR_SET - 0x2C
   1611   { sizeof (EFI_IFR_READ), 0 },                // EFI_IFR_READ - 0x2D
   1612   { sizeof (EFI_IFR_WRITE), 0 },               // EFI_IFR_WRITE - 0x2E
   1613   { sizeof (EFI_IFR_EQUAL), 0 },               // EFI_IFR_EQUAL_OP - 0x2F
   1614   { sizeof (EFI_IFR_NOT_EQUAL), 0 },           // EFI_IFR_NOT_EQUAL_OP
   1615   { sizeof (EFI_IFR_GREATER_THAN), 0 },        // EFI_IFR_GREATER_THAN_OP
   1616   { sizeof (EFI_IFR_GREATER_EQUAL), 0 },       // EFI_IFR_GREATER_EQUAL_OP
   1617   { sizeof (EFI_IFR_LESS_THAN), 0 },           // EFI_IFR_LESS_THAN_OP
   1618   { sizeof (EFI_IFR_LESS_EQUAL), 0 },          // EFI_IFR_LESS_EQUAL_OP - 0x34
   1619   { sizeof (EFI_IFR_BITWISE_AND), 0 },         // EFI_IFR_BITWISE_AND_OP
   1620   { sizeof (EFI_IFR_BITWISE_OR), 0 },          // EFI_IFR_BITWISE_OR_OP
   1621   { sizeof (EFI_IFR_BITWISE_NOT), 0 },         // EFI_IFR_BITWISE_NOT_OP
   1622   { sizeof (EFI_IFR_SHIFT_LEFT), 0 },          // EFI_IFR_SHIFT_LEFT_OP
   1623   { sizeof (EFI_IFR_SHIFT_RIGHT), 0 },         // EFI_IFR_SHIFT_RIGHT_OP
   1624   { sizeof (EFI_IFR_ADD), 0 },                 // EFI_IFR_ADD_OP - 0x3A
   1625   { sizeof (EFI_IFR_SUBTRACT), 0 },            // EFI_IFR_SUBTRACT_OP
   1626   { sizeof (EFI_IFR_MULTIPLY), 0 },            // EFI_IFR_MULTIPLY_OP
   1627   { sizeof (EFI_IFR_DIVIDE), 0 },              // EFI_IFR_DIVIDE_OP
   1628   { sizeof (EFI_IFR_MODULO), 0 },              // EFI_IFR_MODULO_OP - 0x3E
   1629   { sizeof (EFI_IFR_RULE_REF), 0 },            // EFI_IFR_RULE_REF_OP
   1630   { sizeof (EFI_IFR_QUESTION_REF1), 0 },       // EFI_IFR_QUESTION_REF1_OP
   1631   { sizeof (EFI_IFR_QUESTION_REF2), 0 },       // EFI_IFR_QUESTION_REF2_OP - 0x41
   1632   { sizeof (EFI_IFR_UINT8), 0},                // EFI_IFR_UINT8
   1633   { sizeof (EFI_IFR_UINT16), 0},               // EFI_IFR_UINT16
   1634   { sizeof (EFI_IFR_UINT32), 0},               // EFI_IFR_UINT32
   1635   { sizeof (EFI_IFR_UINT64), 0},               // EFI_IFR_UTNT64
   1636   { sizeof (EFI_IFR_TRUE), 0 },                // EFI_IFR_TRUE_OP - 0x46
   1637   { sizeof (EFI_IFR_FALSE), 0 },               // EFI_IFR_FALSE_OP
   1638   { sizeof (EFI_IFR_TO_UINT), 0 },             // EFI_IFR_TO_UINT_OP
   1639   { sizeof (EFI_IFR_TO_STRING), 0 },           // EFI_IFR_TO_STRING_OP
   1640   { sizeof (EFI_IFR_TO_BOOLEAN), 0 },          // EFI_IFR_TO_BOOLEAN_OP
   1641   { sizeof (EFI_IFR_MID), 0 },                 // EFI_IFR_MID_OP
   1642   { sizeof (EFI_IFR_FIND), 0 },                // EFI_IFR_FIND_OP
   1643   { sizeof (EFI_IFR_TOKEN), 0 },               // EFI_IFR_TOKEN_OP
   1644   { sizeof (EFI_IFR_STRING_REF1), 0 },         // EFI_IFR_STRING_REF1_OP - 0x4E
   1645   { sizeof (EFI_IFR_STRING_REF2), 0 },         // EFI_IFR_STRING_REF2_OP
   1646   { sizeof (EFI_IFR_CONDITIONAL), 0 },         // EFI_IFR_CONDITIONAL_OP
   1647   { sizeof (EFI_IFR_QUESTION_REF3), 0 },       // EFI_IFR_QUESTION_REF3_OP
   1648   { sizeof (EFI_IFR_ZERO), 0 },                // EFI_IFR_ZERO_OP
   1649   { sizeof (EFI_IFR_ONE), 0 },                 // EFI_IFR_ONE_OP
   1650   { sizeof (EFI_IFR_ONES), 0 },                // EFI_IFR_ONES_OP
   1651   { sizeof (EFI_IFR_UNDEFINED), 0 },           // EFI_IFR_UNDEFINED_OP
   1652   { sizeof (EFI_IFR_LENGTH), 0 },              // EFI_IFR_LENGTH_OP
   1653   { sizeof (EFI_IFR_DUP), 0 },                 // EFI_IFR_DUP_OP - 0x57
   1654   { sizeof (EFI_IFR_THIS), 0 },                // EFI_IFR_THIS_OP
   1655   { sizeof (EFI_IFR_SPAN), 0 },                // EFI_IFR_SPAN_OP
   1656   { sizeof (EFI_IFR_VALUE), 1 },               // EFI_IFR_VALUE_OP
   1657   { sizeof (EFI_IFR_DEFAULT), 0 },             // EFI_IFR_DEFAULT_OP
   1658   { sizeof (EFI_IFR_DEFAULTSTORE), 0 },        // EFI_IFR_DEFAULTSTORE_OP - 0x5C
   1659   { sizeof (EFI_IFR_FORM_MAP), 1},             // EFI_IFR_FORM_MAP_OP - 0x5D
   1660   { sizeof (EFI_IFR_CATENATE), 0 },            // EFI_IFR_CATENATE_OP
   1661   { sizeof (EFI_IFR_GUID), 0 },                // EFI_IFR_GUID_OP
   1662   { sizeof (EFI_IFR_SECURITY), 0 },            // EFI_IFR_SECURITY_OP - 0x60
   1663   { sizeof (EFI_IFR_MODAL_TAG), 0},            // EFI_IFR_MODAL_TAG_OP - 0x61
   1664   { sizeof (EFI_IFR_REFRESH_ID), 0},           // EFI_IFR_REFRESH_ID_OP - 0x62
   1665   { sizeof (EFI_IFR_WARNING_IF), 1},           // EFI_IFR_WARNING_IF_OP - 0x63
   1666   { sizeof (EFI_IFR_MATCH2), 0 },              // EFI_IFR_MATCH2_OP - 0x64
   1667 };
   1668 
   1669 #ifdef CIFROBJ_DEUBG
   1670 static struct {
   1671   CHAR8 *mIfrName;
   1672 } gIfrObjPrintDebugTable[] = {
   1673   "EFI_IFR_INVALID",    "EFI_IFR_FORM",                 "EFI_IFR_SUBTITLE",      "EFI_IFR_TEXT",            "EFI_IFR_IMAGE",         "EFI_IFR_ONE_OF",
   1674   "EFI_IFR_CHECKBOX",   "EFI_IFR_NUMERIC",              "EFI_IFR_PASSWORD",      "EFI_IFR_ONE_OF_OPTION",   "EFI_IFR_SUPPRESS_IF",   "EFI_IFR_LOCKED",
   1675   "EFI_IFR_ACTION",     "EFI_IFR_RESET_BUTTON",         "EFI_IFR_FORM_SET",      "EFI_IFR_REF",             "EFI_IFR_NO_SUBMIT_IF",  "EFI_IFR_INCONSISTENT_IF",
   1676   "EFI_IFR_EQ_ID_VAL",  "EFI_IFR_EQ_ID_ID",             "EFI_IFR_EQ_ID_LIST",    "EFI_IFR_AND",             "EFI_IFR_OR",            "EFI_IFR_NOT",
   1677   "EFI_IFR_RULE",       "EFI_IFR_GRAY_OUT_IF",          "EFI_IFR_DATE",          "EFI_IFR_TIME",            "EFI_IFR_STRING",        "EFI_IFR_REFRESH",
   1678   "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID",              "EFI_IFR_TO_LOWER",      "EFI_IFR_TO_UPPER",        "EFI_IFR_MAP",           "EFI_IFR_ORDERED_LIST",
   1679   "EFI_IFR_VARSTORE",   "EFI_IFR_VARSTORE_NAME_VALUE",  "EFI_IFR_VARSTORE_EFI",  "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION",       "EFI_IFR_END",
   1680   "EFI_IFR_MATCH",      "EFI_IFR_GET",                  "EFI_IFR_SET",           "EFI_IFR_READ",            "EFI_IFR_WRITE",         "EFI_IFR_EQUAL",
   1681   "EFI_IFR_NOT_EQUAL",  "EFI_IFR_GREATER_THAN",         "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN",       "EFI_IFR_LESS_EQUAL",    "EFI_IFR_BITWISE_AND",
   1682   "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT",          "EFI_IFR_SHIFT_LEFT",    "EFI_IFR_SHIFT_RIGHT",     "EFI_IFR_ADD",           "EFI_IFR_SUBTRACT",
   1683   "EFI_IFR_MULTIPLY",   "EFI_IFR_DIVIDE",               "EFI_IFR_MODULO",        "EFI_IFR_RULE_REF",        "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",
   1684   "EFI_IFR_UINT8",      "EFI_IFR_UINT16",               "EFI_IFR_UINT32",        "EFI_IFR_UINT64",          "EFI_IFR_TRUE",          "EFI_IFR_FALSE",
   1685   "EFI_IFR_TO_UINT",    "EFI_IFR_TO_STRING",            "EFI_IFR_TO_BOOLEAN",    "EFI_IFR_MID",             "EFI_IFR_FIND",          "EFI_IFR_TOKEN",
   1686   "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2",          "EFI_IFR_CONDITIONAL",   "EFI_IFR_QUESTION_REF3",   "EFI_IFR_ZERO",          "EFI_IFR_ONE",
   1687   "EFI_IFR_ONES",       "EFI_IFR_UNDEFINED",            "EFI_IFR_LENGTH",        "EFI_IFR_DUP",             "EFI_IFR_THIS",          "EFI_IFR_SPAN",
   1688   "EFI_IFR_VALUE",      "EFI_IFR_DEFAULT",              "EFI_IFR_DEFAULTSTORE",  "EFI_IFR_FORM_MAP",        "EFI_IFR_CATENATE",      "EFI_IFR_GUID",
   1689   "EFI_IFR_SECURITY",   "EFI_IFR_MODAL_TAG",            "EFI_IFR_REFRESH_ID",    "EFI_IFR_WARNING_IF",      "EFI_IFR_MATCH2",
   1690 };
   1691 
   1692 VOID
   1693 CIFROBJ_DEBUG_PRINT (
   1694   IN UINT8 OpCode
   1695   )
   1696 {
   1697   printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);
   1698 }
   1699 #else
   1700 
   1701 #define CIFROBJ_DEBUG_PRINT(OpCode)
   1702 
   1703 #endif
   1704 
   1705 BOOLEAN gCreateOp = TRUE;
   1706 
   1707 CIfrObj::CIfrObj (
   1708   IN  UINT8   OpCode,
   1709   OUT CHAR8   **IfrObj,
   1710   IN  UINT8   ObjBinLen,
   1711   IN  BOOLEAN DelayEmit
   1712   )
   1713 {
   1714   mDelayEmit   = DelayEmit;
   1715   mPkgOffset   = gCFormPkg.GetPkgLength ();
   1716   mObjBinLen   = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;
   1717   mObjBinBuf   = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];
   1718   mRecordIdx   = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;
   1719 
   1720   if (IfrObj != NULL) {
   1721     *IfrObj    = mObjBinBuf;
   1722   }
   1723 
   1724   CIFROBJ_DEBUG_PRINT (OpCode);
   1725 }
   1726 
   1727 CIfrObj::~CIfrObj (
   1728   VOID
   1729   )
   1730 {
   1731   if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {
   1732     _EMIT_PENDING_OBJ ();
   1733   }
   1734 
   1735   gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);
   1736 }
   1737 
   1738 /*
   1739  * The definition of CIfrObj's member function
   1740  */
   1741 UINT8 gScopeCount = 0;
   1742 
   1743 CIfrOpHeader::CIfrOpHeader (
   1744   IN UINT8 OpCode,
   1745   IN VOID *StartAddr,
   1746   IN UINT8 Length
   1747   ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr)
   1748 {
   1749   mHeader->OpCode = OpCode;
   1750   mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;
   1751   mHeader->Scope  = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;
   1752 }
   1753 
   1754 CIfrOpHeader::CIfrOpHeader (
   1755   IN CIfrOpHeader &OpHdr
   1756   )
   1757 {
   1758   mHeader = OpHdr.mHeader;
   1759 }
   1760 
   1761 UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };
   1762