• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SPendingAssign(IN CHAR8 * Key,IN VOID * Addr,IN UINT32 Len,IN UINT32 LineNo,IN CONST CHAR8 * Msg)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 
~SPendingAssign(VOID)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
SetAddrAndLen(IN VOID * Addr,IN UINT32 LineNo)70 SPendingAssign::SetAddrAndLen (
71   IN VOID   *Addr,
72   IN UINT32 LineNo
73   )
74 {
75   mAddr   = Addr;
76   mLineNo = LineNo;
77 }
78 
79 VOID
AssignValue(IN VOID * Addr,IN UINT32 Len)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 *
GetKey(VOID)90 SPendingAssign::GetKey (
91   VOID
92   )
93 {
94   return mKey;
95 }
96 
CFormPkg(IN UINT32 BufferSize)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 
~CFormPkg()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 *
CreateNewNode(VOID)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 *
IfrBinBufferGet(IN UINT32 Len)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
GetPkgLength(VOID)224 CFormPkg::GetPkgLength (
225   VOID
226   )
227 {
228   return mPkgLength;
229 }
230 
231 VOID
Open(VOID)232 CFormPkg::Open (
233   VOID
234   )
235 {
236   mReadBufferNode   = mBufferNodeQueueHead;
237   mReadBufferOffset = 0;
238 }
239 
240 VOID
Close(VOID)241 CFormPkg::Close (
242   VOID
243   )
244 {
245   mReadBufferNode   = NULL;
246   mReadBufferOffset = 0;
247 }
248 
249 UINT32
Read(IN CHAR8 * Buffer,IN UINT32 Size)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
BuildPkgHdr(OUT EFI_HII_PACKAGE_HEADER ** PkgHdr)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
BuildPkg(OUT PACKAGE_DATA & TBuffer)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
BuildPkg(IN FILE * Output,IN PACKAGE_DATA * PkgData)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
_WRITE_PKG_LINE(IN FILE * pFile,IN UINT32 LineBytes,IN CONST CHAR8 * LineHeader,IN CHAR8 * BlkBuf,IN UINT32 BlkSize)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
_WRITE_PKG_END(IN FILE * pFile,IN UINT32 LineBytes,IN CONST CHAR8 * LineHeader,IN CHAR8 * BlkBuf,IN UINT32 BlkSize)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
GenCFile(IN CHAR8 * BaseName,IN FILE * pFile,IN PACKAGE_DATA * PkgData)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
AssignPending(IN CHAR8 * Key,IN VOID * ValAddr,IN UINT32 ValLen,IN UINT32 LineNo,IN CONST CHAR8 * Msg)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
DoPendingAssign(IN CHAR8 * Key,IN VOID * ValAddr,IN UINT32 ValLen)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
HavePendingUnassigned(VOID)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
PendingAssignPrintAll(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 *
GetBinBufferNodeForAddr(IN CHAR8 * BinBuffAddr)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 *
GetNodeBefore(IN SBufferNode * CurrentNode)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
InsertNodeBefore(IN SBufferNode * CurrentNode,IN SBufferNode * NewNode)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 *
GetBufAddrBaseOnOffset(IN UINT32 Offset)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
AdjustDynamicInsertOpcode(IN CHAR8 * LastFormEndAddr,IN CHAR8 * InsertOpcodeAddr)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
DeclarePendingQuestion(IN CVfrVarDataTypeDB & lCVfrVarDataTypeDB,IN CVfrDataStorage & lCVfrDataStorage,IN CVfrQuestionDB & lCVfrQuestionDB,IN EFI_GUID * LocalFormSetGuid,IN UINT32 LineNo,OUT CHAR8 ** InsertOpcodeAddr)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 
SIfrRecord(VOID)953 SIfrRecord::SIfrRecord (
954   VOID
955   )
956 {
957   mIfrBinBuf = NULL;
958   mBinBufLen = 0;
959   mLineNo    = 0xFFFFFFFF;
960   mOffset    = 0xFFFFFFFF;
961   mNext      = NULL;
962 }
963 
~SIfrRecord(VOID)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 
CIfrRecordInfoDB(VOID)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 
~CIfrRecordInfoDB(VOID)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 *
GetRecordInfoFromIdx(IN UINT32 RecordIdx)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
IfrRecordRegister(IN UINT32 LineNo,IN CHAR8 * IfrBinBuf,IN UINT8 BinBufLen,IN UINT32 Offset)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
IfrRecordInfoUpdate(IN UINT32 RecordIdx,IN UINT32 LineNo,IN CHAR8 * BinBuf,IN UINT8 BinBufLen,IN UINT32 Offset)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
IfrRecordOutput(OUT PACKAGE_DATA & TBuffer)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
IfrRecordOutput(IN FILE * File,IN UINT32 LineNo)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
CheckQuestionOpCode(IN UINT8 OpCode)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
CheckIdOpCode(IN UINT8 OpCode)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
GetOpcodeQuestionId(IN EFI_IFR_OP_HEADER * OpHead)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 *
GetRecordInfoFromOffset(IN UINT32 Offset)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
IfrAdjustDynamicOpcodeInRecords(VOID)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
IfrAdjustOffsetForRecord(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
IfrRecordAdjust(VOID)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
_EMIT_PENDING_OBJ(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
CIFROBJ_DEBUG_PRINT(IN UINT8 OpCode)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 
CIfrObj(IN UINT8 OpCode,OUT CHAR8 ** IfrObj,IN UINT8 ObjBinLen,IN BOOLEAN DelayEmit)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 
~CIfrObj(VOID)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 
CIfrOpHeader(IN UINT8 OpCode,IN VOID * StartAddr,IN UINT8 Length)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 
CIfrOpHeader(IN CIfrOpHeader & OpHdr)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