1 /** @file
2 
3   The definition of CFormPkg's member function
4 
5 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "stdio.h"
11 #include "assert.h"
12 #include "VfrFormPkg.h"
13 
14 /*
15  * The definition of CFormPkg's member function
16  */
17 
SPendingAssign(IN CHAR8 * Key,IN VOID * Addr,IN UINT32 Len,IN UINT32 LineNo,IN CONST CHAR8 * Msg)18 SPendingAssign::SPendingAssign (
19   IN CHAR8  *Key,
20   IN VOID   *Addr,
21   IN UINT32 Len,
22   IN UINT32 LineNo,
23   IN CONST CHAR8  *Msg
24   )
25 {
26   mKey    = NULL;
27   mAddr   = Addr;
28   mLen    = Len;
29   mFlag   = PENDING;
30   mLineNo = LineNo;
31   mMsg    = NULL;
32   mNext   = NULL;
33   if (Key != NULL) {
34     mKey = new CHAR8[strlen (Key) + 1];
35     if (mKey != NULL) {
36       strcpy (mKey, Key);
37     }
38   }
39 
40   if (Msg != NULL) {
41     mMsg = new CHAR8[strlen (Msg) + 1];
42     if (mMsg != NULL) {
43       strcpy (mMsg, Msg);
44     }
45   }
46 }
47 
~SPendingAssign(VOID)48 SPendingAssign::~SPendingAssign (
49   VOID
50   )
51 {
52   if (mKey != NULL) {
53     delete[] mKey;
54   }
55   mAddr   = NULL;
56   mLen    = 0;
57   mLineNo = 0;
58   if (mMsg != NULL) {
59     delete[] mMsg;
60   }
61   mNext   = NULL;
62 }
63 
64 VOID
SetAddrAndLen(IN VOID * Addr,IN UINT32 LineNo)65 SPendingAssign::SetAddrAndLen (
66   IN VOID   *Addr,
67   IN UINT32 LineNo
68   )
69 {
70   mAddr   = Addr;
71   mLineNo = LineNo;
72 }
73 
74 VOID
AssignValue(IN VOID * Addr,IN UINT32 Len)75 SPendingAssign::AssignValue (
76   IN VOID   *Addr,
77   IN UINT32 Len
78   )
79 {
80   memmove (mAddr, Addr, (mLen < Len ? mLen : Len));
81   mFlag = ASSIGNED;
82 }
83 
84 CHAR8 *
GetKey(VOID)85 SPendingAssign::GetKey (
86   VOID
87   )
88 {
89   return mKey;
90 }
91 
CFormPkg(IN UINT32 BufferSize)92 CFormPkg::CFormPkg (
93   IN UINT32 BufferSize
94   )
95 {
96   CHAR8       *BufferStart;
97   CHAR8       *BufferEnd;
98   SBufferNode *Node;
99 
100   mPkgLength           = 0;
101   mBufferSize          = 0;
102   mBufferNodeQueueHead = NULL;
103   mBufferNodeQueueTail = NULL;
104   mCurrBufferNode      = NULL;
105   mReadBufferNode      = NULL;
106   mReadBufferOffset    = 0;
107   PendingAssignList    = NULL;
108 
109   Node = new SBufferNode;
110   if (Node == NULL) {
111     return ;
112   }
113   BufferStart = new CHAR8[BufferSize];
114   if (BufferStart == NULL) {
115     delete Node;
116     return;
117   }
118   BufferEnd   = BufferStart + BufferSize;
119 
120   memset (BufferStart, 0, BufferSize);
121   Node->mBufferStart   = BufferStart;
122   Node->mBufferEnd     = BufferEnd;
123   Node->mBufferFree    = BufferStart;
124   Node->mNext          = NULL;
125 
126   mBufferSize          = BufferSize;
127   mBufferNodeQueueHead = Node;
128   mBufferNodeQueueTail = Node;
129   mCurrBufferNode      = Node;
130 }
131 
~CFormPkg()132 CFormPkg::~CFormPkg ()
133 {
134   SBufferNode    *pBNode;
135   SPendingAssign *pPNode;
136 
137   while (mBufferNodeQueueHead != NULL) {
138     pBNode = mBufferNodeQueueHead;
139     mBufferNodeQueueHead = mBufferNodeQueueHead->mNext;
140     if (pBNode->mBufferStart != NULL) {
141       delete[] pBNode->mBufferStart;
142       delete pBNode;
143     }
144   }
145   mBufferNodeQueueTail = NULL;
146   mCurrBufferNode      = NULL;
147 
148   while (PendingAssignList != NULL) {
149     pPNode = PendingAssignList;
150     PendingAssignList = PendingAssignList->mNext;
151     delete pPNode;
152   }
153   PendingAssignList = NULL;
154 }
155 
156 SBufferNode *
CreateNewNode(VOID)157 CFormPkg::CreateNewNode (
158   VOID
159   )
160 {
161   SBufferNode *Node;
162 
163   Node = new SBufferNode;
164   if (Node == NULL) {
165     return NULL;
166   }
167 
168   Node->mBufferStart = new CHAR8[mBufferSize];
169   if (Node->mBufferStart == NULL) {
170     delete Node;
171     return NULL;
172   } else {
173     memset (Node->mBufferStart, 0, mBufferSize);
174     Node->mBufferEnd  = Node->mBufferStart + mBufferSize;
175     Node->mBufferFree = Node->mBufferStart;
176     Node->mNext       = NULL;
177   }
178 
179   return Node;
180 }
181 
182 CHAR8 *
IfrBinBufferGet(IN UINT32 Len)183 CFormPkg::IfrBinBufferGet (
184   IN UINT32 Len
185   )
186 {
187   CHAR8       *BinBuffer = NULL;
188   SBufferNode *Node      = NULL;
189 
190   if ((Len == 0) || (Len > mBufferSize)) {
191     return NULL;
192   }
193 
194   if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) {
195     BinBuffer = mCurrBufferNode->mBufferFree;
196     mCurrBufferNode->mBufferFree += Len;
197   } else {
198     Node = CreateNewNode ();
199     if (Node == NULL) {
200       return NULL;
201     }
202 
203     if (mBufferNodeQueueTail == NULL) {
204       mBufferNodeQueueHead = mBufferNodeQueueTail = Node;
205     } else {
206       mBufferNodeQueueTail->mNext = Node;
207       mBufferNodeQueueTail = Node;
208     }
209     mCurrBufferNode = Node;
210 
211     //
212     // Now try again.
213     //
214     BinBuffer = mCurrBufferNode->mBufferFree;
215     mCurrBufferNode->mBufferFree += Len;
216   }
217 
218   mPkgLength += Len;
219 
220   return BinBuffer;
221 }
222 
223 inline
224 UINT32
GetPkgLength(VOID)225 CFormPkg::GetPkgLength (
226   VOID
227   )
228 {
229   return mPkgLength;
230 }
231 
232 VOID
Open(VOID)233 CFormPkg::Open (
234   VOID
235   )
236 {
237   mReadBufferNode   = mBufferNodeQueueHead;
238   mReadBufferOffset = 0;
239 }
240 
241 VOID
Close(VOID)242 CFormPkg::Close (
243   VOID
244   )
245 {
246   mReadBufferNode   = NULL;
247   mReadBufferOffset = 0;
248 }
249 
250 UINT32
Read(IN CHAR8 * Buffer,IN UINT32 Size)251 CFormPkg::Read (
252   IN CHAR8     *Buffer,
253   IN UINT32    Size
254   )
255 {
256   UINT32       Index;
257 
258   if ((Size == 0) || (Buffer == NULL)) {
259     return 0;
260   }
261 
262   if (mReadBufferNode == NULL) {
263     return 0;
264   }
265 
266   for (Index = 0; Index < Size; Index++) {
267     if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) {
268       Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];
269     } else {
270       if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) {
271         return Index;
272       } else {
273         mReadBufferOffset = 0;
274         Index --;
275       }
276     }
277   }
278 
279   return Size;
280 }
281 
282 EFI_VFR_RETURN_CODE
BuildPkgHdr(OUT EFI_HII_PACKAGE_HEADER ** PkgHdr)283 CFormPkg::BuildPkgHdr (
284   OUT EFI_HII_PACKAGE_HEADER **PkgHdr
285   )
286 {
287   if (PkgHdr == NULL) {
288     return VFR_RETURN_FATAL_ERROR;
289   }
290 
291   if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) {
292     return VFR_RETURN_OUT_FOR_RESOURCES;
293   }
294 
295   (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM;
296   (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER);
297 
298   return VFR_RETURN_SUCCESS;
299 }
300 
301 EFI_VFR_RETURN_CODE
BuildPkg(OUT PACKAGE_DATA & TBuffer)302 CFormPkg::BuildPkg (
303   OUT PACKAGE_DATA &TBuffer
304   )
305 {
306 
307   CHAR8  *Temp;
308   UINT32 Size;
309   CHAR8  Buffer[1024];
310 
311   if (TBuffer.Buffer != NULL) {
312     delete TBuffer.Buffer;
313   }
314 
315   TBuffer.Size = mPkgLength;
316   TBuffer.Buffer = NULL;
317   if (TBuffer.Size != 0) {
318     TBuffer.Buffer = new CHAR8[TBuffer.Size];
319   } else {
320     return VFR_RETURN_SUCCESS;
321   }
322 
323   Temp = TBuffer.Buffer;
324   Open ();
325   while ((Size = Read (Buffer, 1024)) != 0) {
326     memcpy (Temp, Buffer, Size);
327     Temp += Size;
328   }
329   Close ();
330   return VFR_RETURN_SUCCESS;
331 }
332 
333 
334 EFI_VFR_RETURN_CODE
BuildPkg(IN FILE * Output,IN PACKAGE_DATA * PkgData)335 CFormPkg::BuildPkg (
336   IN FILE  *Output,
337   IN PACKAGE_DATA *PkgData
338   )
339 {
340   EFI_VFR_RETURN_CODE     Ret;
341   CHAR8                   Buffer[1024];
342   UINT32                  Size;
343   EFI_HII_PACKAGE_HEADER  *PkgHdr;
344 
345   if (Output == NULL) {
346     return VFR_RETURN_FATAL_ERROR;
347   }
348 
349   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
350     return Ret;
351   }
352   fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);
353   delete PkgHdr;
354 
355   if (PkgData == NULL) {
356     Open ();
357     while ((Size = Read (Buffer, 1024)) != 0) {
358       fwrite (Buffer, Size, 1, Output);
359     }
360     Close ();
361   } else {
362     fwrite (PkgData->Buffer, PkgData->Size, 1, Output);
363   }
364 
365   return VFR_RETURN_SUCCESS;
366 }
367 
368 VOID
_WRITE_PKG_LINE(IN FILE * pFile,IN UINT32 LineBytes,IN CONST CHAR8 * LineHeader,IN CHAR8 * BlkBuf,IN UINT32 BlkSize)369 CFormPkg::_WRITE_PKG_LINE (
370   IN FILE         *pFile,
371   IN UINT32       LineBytes,
372   IN CONST CHAR8  *LineHeader,
373   IN CHAR8        *BlkBuf,
374   IN UINT32       BlkSize
375   )
376 {
377   UINT32    Index;
378 
379   if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
380     return;
381   }
382 
383   for (Index = 0; Index < BlkSize; Index++) {
384     if ((Index % LineBytes) == 0) {
385       fprintf (pFile, "\n%s", LineHeader);
386     }
387     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
388   }
389 }
390 
391 VOID
_WRITE_PKG_END(IN FILE * pFile,IN UINT32 LineBytes,IN CONST CHAR8 * LineHeader,IN CHAR8 * BlkBuf,IN UINT32 BlkSize)392 CFormPkg::_WRITE_PKG_END (
393   IN FILE         *pFile,
394   IN UINT32       LineBytes,
395   IN CONST CHAR8  *LineHeader,
396   IN CHAR8        *BlkBuf,
397   IN UINT32       BlkSize
398   )
399 {
400   UINT32    Index;
401 
402   if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
403     return;
404   }
405 
406   for (Index = 0; Index < BlkSize - 1; Index++) {
407     if ((Index % LineBytes) == 0) {
408       fprintf (pFile, "\n%s", LineHeader);
409     }
410     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);
411   }
412 
413   if ((Index % LineBytes) == 0) {
414     fprintf (pFile, "\n%s", LineHeader);
415   }
416   fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);
417 }
418 
419 #define BYTES_PRE_LINE 0x10
420 UINT32   gAdjustOpcodeOffset = 0;
421 BOOLEAN  gNeedAdjustOpcode   = FALSE;
422 UINT32   gAdjustOpcodeLen    = 0;
423 
424 EFI_VFR_RETURN_CODE
GenCFile(IN CHAR8 * BaseName,IN FILE * pFile,IN PACKAGE_DATA * PkgData)425 CFormPkg::GenCFile (
426   IN CHAR8 *BaseName,
427   IN FILE *pFile,
428   IN PACKAGE_DATA *PkgData
429   )
430 {
431   EFI_VFR_RETURN_CODE          Ret;
432   CHAR8                        Buffer[BYTES_PRE_LINE * 8];
433   EFI_HII_PACKAGE_HEADER       *PkgHdr;
434   UINT32                       PkgLength  = 0;
435   UINT32                       ReadSize   = 0;
436 
437   if ((BaseName == NULL) || (pFile == NULL)) {
438     return VFR_RETURN_FATAL_ERROR;
439   }
440 
441   fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);
442 
443   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
444     return Ret;
445   }
446 
447 
448   fprintf (pFile, "  // ARRAY LENGTH\n");
449   PkgLength = PkgHdr->Length + sizeof (UINT32);
450   _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));
451 
452   fprintf (pFile, "\n\n  // PACKAGE HEADER\n");
453   _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));
454   PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);
455 
456   fprintf (pFile, "\n\n  // PACKAGE DATA\n");
457 
458   if (PkgData == NULL) {
459     Open ();
460     while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {
461       PkgLength += ReadSize;
462       if (PkgLength < PkgHdr->Length) {
463         _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
464       } else {
465         _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);
466       }
467     }
468     Close ();
469   } else {
470     if (PkgData->Size % BYTES_PRE_LINE != 0) {
471       PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE);
472       _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
473       _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE);
474     } else {
475       PkgLength = PkgData->Size - BYTES_PRE_LINE;
476       _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer, PkgLength);
477       _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE);
478     }
479   }
480 
481   delete PkgHdr;
482   fprintf (pFile, "\n};\n");
483 
484   return VFR_RETURN_SUCCESS;
485 }
486 
487 EFI_VFR_RETURN_CODE
AssignPending(IN CHAR8 * Key,IN VOID * ValAddr,IN UINT32 ValLen,IN UINT32 LineNo,IN CONST CHAR8 * Msg)488 CFormPkg::AssignPending (
489   IN CHAR8  *Key,
490   IN VOID   *ValAddr,
491   IN UINT32 ValLen,
492   IN UINT32 LineNo,
493   IN CONST CHAR8  *Msg
494   )
495 {
496   SPendingAssign *pNew;
497 
498   pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);
499   if (pNew == NULL) {
500     return VFR_RETURN_OUT_FOR_RESOURCES;
501   }
502 
503   pNew->mNext       = PendingAssignList;
504   PendingAssignList = pNew;
505   return VFR_RETURN_SUCCESS;
506 }
507 
508 VOID
DoPendingAssign(IN CHAR8 * Key,IN VOID * ValAddr,IN UINT32 ValLen)509 CFormPkg::DoPendingAssign (
510   IN CHAR8  *Key,
511   IN VOID   *ValAddr,
512   IN UINT32 ValLen
513   )
514 {
515   SPendingAssign *pNode;
516 
517   if ((Key == NULL) || (ValAddr == NULL)) {
518     return;
519   }
520 
521   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
522     if (strcmp (pNode->mKey, Key) == 0) {
523       pNode->AssignValue (ValAddr, ValLen);
524     }
525   }
526 }
527 
528 bool
HavePendingUnassigned(VOID)529 CFormPkg::HavePendingUnassigned (
530   VOID
531   )
532 {
533   SPendingAssign *pNode;
534 
535   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
536     if (pNode->mFlag == PENDING) {
537       return TRUE;
538     }
539   }
540 
541   return FALSE;
542 }
543 
544 VOID
PendingAssignPrintAll(VOID)545 CFormPkg::PendingAssignPrintAll (
546   VOID
547   )
548 {
549   SPendingAssign *pNode;
550 
551   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
552     if (pNode->mFlag == PENDING) {
553       gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);
554     }
555   }
556 }
557 
558 SBufferNode *
GetBinBufferNodeForAddr(IN CHAR8 * BinBuffAddr)559 CFormPkg::GetBinBufferNodeForAddr (
560   IN CHAR8              *BinBuffAddr
561   )
562 {
563   SBufferNode *TmpNode;
564 
565   TmpNode = mBufferNodeQueueHead;
566 
567   while (TmpNode != NULL) {
568     if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) {
569       return TmpNode;
570     }
571 
572     TmpNode = TmpNode->mNext;
573   }
574 
575   return NULL;
576 }
577 
578 SBufferNode *
GetNodeBefore(IN SBufferNode * CurrentNode)579 CFormPkg::GetNodeBefore(
580   IN SBufferNode *CurrentNode
581   )
582 {
583   SBufferNode *FirstNode   = mBufferNodeQueueHead;
584   SBufferNode *LastNode    = mBufferNodeQueueHead;
585 
586   while (FirstNode != NULL) {
587     if (FirstNode == CurrentNode) {
588       break;
589     }
590 
591     LastNode    = FirstNode;
592     FirstNode   = FirstNode->mNext;
593   }
594 
595   if (FirstNode == NULL) {
596     LastNode = NULL;
597   }
598 
599   return LastNode;
600 }
601 
602 EFI_VFR_RETURN_CODE
InsertNodeBefore(IN SBufferNode * CurrentNode,IN SBufferNode * NewNode)603 CFormPkg::InsertNodeBefore(
604   IN SBufferNode *CurrentNode,
605   IN SBufferNode *NewNode
606   )
607 {
608   SBufferNode *LastNode = GetNodeBefore (CurrentNode);
609 
610   if (LastNode == NULL) {
611     return VFR_RETURN_MISMATCHED;
612   }
613 
614   NewNode->mNext = LastNode->mNext;
615   LastNode->mNext = NewNode;
616 
617   return VFR_RETURN_SUCCESS;
618 }
619 
620 CHAR8 *
GetBufAddrBaseOnOffset(IN UINT32 Offset)621 CFormPkg::GetBufAddrBaseOnOffset (
622   IN UINT32      Offset
623   )
624 {
625   SBufferNode *TmpNode;
626   UINT32      TotalBufLen;
627   UINT32      CurrentBufLen;
628 
629   TotalBufLen = 0;
630 
631   for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) {
632     CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart;
633     if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) {
634       return TmpNode->mBufferStart + (Offset - TotalBufLen);
635     }
636 
637     TotalBufLen += CurrentBufLen;
638   }
639 
640   return NULL;
641 }
642 
643 EFI_VFR_RETURN_CODE
AdjustDynamicInsertOpcode(IN CHAR8 * InserPositionAddr,IN CHAR8 * InsertOpcodeAddr,IN BOOLEAN CreateOpcodeAfterParsingVfr)644 CFormPkg::AdjustDynamicInsertOpcode (
645   IN CHAR8              *InserPositionAddr,
646   IN CHAR8              *InsertOpcodeAddr,
647   IN BOOLEAN            CreateOpcodeAfterParsingVfr
648   )
649 {
650   SBufferNode *InserPositionNode;
651   SBufferNode *InsertOpcodeNode;
652   SBufferNode *NewRestoreNodeBegin;
653   SBufferNode *NewRestoreNodeEnd;
654   SBufferNode *NewLastEndNode;
655   SBufferNode *TmpNode;
656   UINT32      NeedRestoreCodeLen;
657 
658   NewRestoreNodeEnd = NULL;
659 
660   InserPositionNode  = GetBinBufferNodeForAddr(InserPositionAddr);
661   InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);
662   assert (InserPositionNode != NULL);
663   assert (InsertOpcodeNode  != NULL);
664 
665   if (InserPositionNode == InsertOpcodeNode) {
666     //
667     // Create New Node to save the restore opcode.
668     //
669     NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;
670     gAdjustOpcodeLen   = NeedRestoreCodeLen;
671     NewRestoreNodeBegin = CreateNewNode ();
672     if (NewRestoreNodeBegin == NULL) {
673       return VFR_RETURN_OUT_FOR_RESOURCES;
674     }
675     memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
676     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
677 
678     //
679     // Override the restore buffer data.
680     //
681     memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
682     InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;
683     memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);
684   } else {
685     //
686     // Create New Node to save the restore opcode.
687     //
688     NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;
689     gAdjustOpcodeLen   = NeedRestoreCodeLen;
690     NewRestoreNodeBegin = CreateNewNode ();
691     if (NewRestoreNodeBegin == NULL) {
692       return VFR_RETURN_OUT_FOR_RESOURCES;
693     }
694     memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
695     NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
696     //
697     // Override the restore buffer data.
698     //
699     InserPositionNode->mBufferFree -= NeedRestoreCodeLen;
700     //
701     // Link the restore data to new node.
702     //
703     NewRestoreNodeBegin->mNext = InserPositionNode->mNext;
704 
705     //
706     // Count the Adjust opcode len.
707     //
708     TmpNode = InserPositionNode->mNext;
709     while (TmpNode != InsertOpcodeNode) {
710       gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;
711       TmpNode = TmpNode->mNext;
712     }
713 
714     //
715     // Create New Node to save the last node of restore opcode.
716     //
717     NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
718     gAdjustOpcodeLen  += NeedRestoreCodeLen;
719     if (NeedRestoreCodeLen > 0) {
720       NewRestoreNodeEnd = CreateNewNode ();
721       if (NewRestoreNodeEnd == NULL) {
722         return VFR_RETURN_OUT_FOR_RESOURCES;
723       }
724       memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen);
725       NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen;
726       //
727       // Override the restore buffer data.
728       //
729       memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
730       InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;
731 
732       //
733       // Insert the last restore data node.
734       //
735       TmpNode = GetNodeBefore (InsertOpcodeNode);
736       assert (TmpNode != NULL);
737 
738       if (TmpNode == InserPositionNode) {
739         NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;
740       } else {
741         TmpNode->mNext = NewRestoreNodeEnd;
742       }
743       //
744       // Connect the dynamic opcode node to the node after InserPositionNode.
745       //
746       InserPositionNode->mNext = InsertOpcodeNode;
747     }
748   }
749 
750   if (CreateOpcodeAfterParsingVfr) {
751     //
752     // Th new opcodes were created after Parsing Vfr file,
753     // so the content in mBufferNodeQueueTail must be the new created opcodes.
754     // So connet the  NewRestoreNodeBegin to the tail and update the tail node.
755     //
756     mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
757     if (NewRestoreNodeEnd != NULL) {
758       mBufferNodeQueueTail = NewRestoreNodeEnd;
759     } else {
760       mBufferNodeQueueTail = NewRestoreNodeBegin;
761     }
762   } else {
763     if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
764       //
765       // End form set opcode all in the mBufferNodeQueueTail node.
766       //
767       NewLastEndNode = CreateNewNode ();
768       if (NewLastEndNode == NULL) {
769         return VFR_RETURN_OUT_FOR_RESOURCES;
770       }
771       NewLastEndNode->mBufferStart[0] = 0x29;
772       NewLastEndNode->mBufferStart[1] = 0x02;
773       NewLastEndNode->mBufferFree += 2;
774 
775       mBufferNodeQueueTail->mBufferFree -= 2;
776 
777       mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
778       if (NewRestoreNodeEnd != NULL) {
779         NewRestoreNodeEnd->mNext = NewLastEndNode;
780       } else {
781         NewRestoreNodeBegin->mNext = NewLastEndNode;
782       }
783 
784       mBufferNodeQueueTail = NewLastEndNode;
785     } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
786       TmpNode = GetNodeBefore(mBufferNodeQueueTail);
787       assert (TmpNode != NULL);
788 
789       TmpNode->mNext = NewRestoreNodeBegin;
790       if (NewRestoreNodeEnd != NULL) {
791         NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
792       } else {
793         NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
794       }
795     }
796   }
797   mCurrBufferNode = mBufferNodeQueueTail;
798   return VFR_RETURN_SUCCESS;
799 }
800 
801 EFI_VFR_RETURN_CODE
DeclarePendingQuestion(IN CVfrVarDataTypeDB & lCVfrVarDataTypeDB,IN CVfrDataStorage & lCVfrDataStorage,IN CVfrQuestionDB & lCVfrQuestionDB,IN EFI_GUID * LocalFormSetGuid,IN UINT32 LineNo,OUT CHAR8 ** InsertOpcodeAddr)802 CFormPkg::DeclarePendingQuestion (
803   IN CVfrVarDataTypeDB   &lCVfrVarDataTypeDB,
804   IN CVfrDataStorage     &lCVfrDataStorage,
805   IN CVfrQuestionDB      &lCVfrQuestionDB,
806   IN EFI_GUID            *LocalFormSetGuid,
807   IN UINT32              LineNo,
808   OUT CHAR8              **InsertOpcodeAddr
809   )
810 {
811   SPendingAssign *pNode;
812   CHAR8          *VarStr;
813   UINT32         ArrayIdx;
814   CHAR8          FName[MAX_NAME_LEN];
815   CHAR8          *SName;
816   CHAR8          *NewStr;
817   UINT32         ShrinkSize = 0;
818   EFI_VFR_RETURN_CODE  ReturnCode;
819   EFI_VFR_VARSTORE_TYPE VarStoreType  = EFI_VFR_VARSTORE_INVALID;
820   UINT8    LFlags;
821   UINT32   MaxValue;
822   CIfrGuid *GuidObj = NULL;
823 
824   //
825   // Declare all questions as Numeric in DisableIf True
826   //
827   // DisableIf
828   CIfrDisableIf DIObj;
829   DIObj.SetLineNo (LineNo);
830   *InsertOpcodeAddr = DIObj.GetObjBinAddr<CHAR8>();
831 
832   //TrueOpcode
833   CIfrTrue TObj (LineNo);
834 
835   // Declare Numeric qeustion for each undefined question.
836   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
837     if (pNode->mFlag == PENDING) {
838       EFI_VARSTORE_INFO Info;
839       EFI_QUESTION_ID   QId   = EFI_QUESTION_ID_INVALID;
840       //
841       // Register this question, assume it is normal question, not date or time question
842       //
843       VarStr = pNode->mKey;
844       ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId);
845       if (ReturnCode != VFR_RETURN_SUCCESS) {
846         gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
847         return ReturnCode;
848       }
849 
850 #ifdef VFREXP_DEBUG
851       printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId);
852 #endif
853       //
854       // Get Question Info, framework vfr VarName == StructName
855       //
856       ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx);
857       if (ReturnCode != VFR_RETURN_SUCCESS) {
858         gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable");
859         return ReturnCode;
860       }
861       //
862       // Get VarStoreType
863       //
864       ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId);
865       if (ReturnCode != VFR_RETURN_SUCCESS) {
866         gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");
867         return ReturnCode;
868       }
869       VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId);
870 
871       if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) {
872         ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx);
873       } else {
874         if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
875           ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);
876         } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) {
877           VarStr = pNode->mKey;
878           //convert VarStr with store name to VarStr with structure name
879           ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName);
880           if (ReturnCode == VFR_RETURN_SUCCESS) {
881             NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1];
882             NewStr[0] = '\0';
883             strcpy (NewStr, SName);
884             strcat (NewStr, VarStr + strlen (FName));
885             ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar);
886             delete[] NewStr;
887           }
888         } else {
889           ReturnCode = VFR_RETURN_UNSUPPORTED;
890         }
891       }
892       if (ReturnCode != VFR_RETURN_SUCCESS) {
893         gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
894         return ReturnCode;
895       }
896       //
897       // If the storage is bit fields, create Guid opcode to wrap the numeric opcode.
898       //
899       if (Info.mIsBitVar) {
900         GuidObj = new CIfrGuid(0);
901         GuidObj->SetGuid (&gEdkiiIfrBitVarGuid);
902         GuidObj->SetLineNo(LineNo);
903       }
904 
905       CIfrNumeric CNObj;
906       CNObj.SetLineNo (LineNo);
907       CNObj.SetPrompt (0x0);
908       CNObj.SetHelp (0x0);
909       CNObj.SetQuestionId (QId);
910       CNObj.SetVarStoreInfo (&Info);
911 
912       //
913       // Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question.
914       //
915       if (Info.mIsBitVar) {
916         MaxValue = (1 << Info.mVarTotalSize) -1;
917         CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0);
918         ShrinkSize = 12;
919         LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize);
920         CNObj.SetFlagsForBitField (0, LFlags);
921       } else {
922         //
923         // Numeric doesn't support BOOLEAN data type.
924         // BOOLEAN type has the same data size to UINT8.
925         //
926         if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
927           Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
928         }
929         CNObj.SetFlags (0, Info.mVarType);
930         //
931         // Use maximum value not to limit the valid value for the undefined question.
932         //
933         switch (Info.mVarType) {
934         case EFI_IFR_TYPE_NUM_SIZE_64:
935           CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
936           ShrinkSize = 0;
937           break;
938         case EFI_IFR_TYPE_NUM_SIZE_32:
939           CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
940           ShrinkSize = 12;
941           break;
942         case EFI_IFR_TYPE_NUM_SIZE_16:
943           CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
944           ShrinkSize = 18;
945           break;
946         case EFI_IFR_TYPE_NUM_SIZE_8:
947           CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
948           ShrinkSize = 21;
949           break;
950         default:
951           break;
952         }
953       }
954       CNObj.ShrinkBinSize (ShrinkSize);
955 
956       //
957       // For undefined Efi VarStore type question
958       // Append the extended guided opcode to contain VarName
959       //
960       if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
961         CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName);
962         CVNObj.SetLineNo (LineNo);
963       }
964 
965       //
966       // End for Numeric
967       //
968       CIfrEnd CEObj;
969       CEObj.SetLineNo (LineNo);
970       //
971       // End for Guided opcode
972       //
973       if (GuidObj != NULL) {
974         CIfrEnd CEObjGuid;
975         CEObjGuid.SetLineNo (LineNo);
976         GuidObj->SetScope(1);
977         delete GuidObj;
978         GuidObj = NULL;
979       }
980     }
981   }
982 
983   //
984   // End for DisableIf
985   //
986   CIfrEnd SEObj;
987   SEObj.SetLineNo (LineNo);
988 
989   return VFR_RETURN_SUCCESS;
990 }
991 
992 CFormPkg gCFormPkg;
993 
SIfrRecord(VOID)994 SIfrRecord::SIfrRecord (
995   VOID
996   )
997 {
998   mIfrBinBuf = NULL;
999   mBinBufLen = 0;
1000   mLineNo    = 0xFFFFFFFF;
1001   mOffset    = 0xFFFFFFFF;
1002   mNext      = NULL;
1003 }
1004 
~SIfrRecord(VOID)1005 SIfrRecord::~SIfrRecord (
1006   VOID
1007   )
1008 {
1009   if (mIfrBinBuf != NULL) {
1010     //delete mIfrBinBuf;
1011     mIfrBinBuf = NULL;
1012   }
1013   mLineNo      = 0xFFFFFFFF;
1014   mOffset      = 0xFFFFFFFF;
1015   mBinBufLen   = 0;
1016   mNext        = NULL;
1017 }
1018 
CIfrRecordInfoDB(VOID)1019 CIfrRecordInfoDB::CIfrRecordInfoDB (
1020   VOID
1021   )
1022 {
1023   mSwitch            = TRUE;
1024   mRecordCount       = EFI_IFR_RECORDINFO_IDX_START;
1025   mIfrRecordListHead = NULL;
1026   mIfrRecordListTail = NULL;
1027   mAllDefaultTypeCount = 0;
1028   for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) {
1029     mAllDefaultIdArray[i] = 0xffff;
1030   }
1031 }
1032 
~CIfrRecordInfoDB(VOID)1033 CIfrRecordInfoDB::~CIfrRecordInfoDB (
1034   VOID
1035   )
1036 {
1037   SIfrRecord *pNode;
1038 
1039   while (mIfrRecordListHead != NULL) {
1040     pNode = mIfrRecordListHead;
1041     mIfrRecordListHead = mIfrRecordListHead->mNext;
1042     delete pNode;
1043   }
1044 }
1045 
1046 SIfrRecord *
GetRecordInfoFromIdx(IN UINT32 RecordIdx)1047 CIfrRecordInfoDB::GetRecordInfoFromIdx (
1048   IN UINT32 RecordIdx
1049   )
1050 {
1051   UINT32     Idx;
1052   SIfrRecord *pNode = NULL;
1053 
1054   if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {
1055     return NULL;
1056   }
1057 
1058   for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead;
1059        (Idx != RecordIdx) && (pNode != NULL);
1060        Idx++, pNode = pNode->mNext)
1061   ;
1062 
1063   return pNode;
1064 }
1065 
1066 UINT32
IfrRecordRegister(IN UINT32 LineNo,IN CHAR8 * IfrBinBuf,IN UINT8 BinBufLen,IN UINT32 Offset)1067 CIfrRecordInfoDB::IfrRecordRegister (
1068   IN UINT32 LineNo,
1069   IN CHAR8  *IfrBinBuf,
1070   IN UINT8  BinBufLen,
1071   IN UINT32 Offset
1072   )
1073 {
1074   SIfrRecord *pNew;
1075 
1076   if (mSwitch == FALSE) {
1077     return EFI_IFR_RECORDINFO_IDX_INVALUD;
1078   }
1079 
1080   if ((pNew = new SIfrRecord) == NULL) {
1081     return EFI_IFR_RECORDINFO_IDX_INVALUD;
1082   }
1083 
1084   if (mIfrRecordListHead == NULL) {
1085     mIfrRecordListHead = pNew;
1086     mIfrRecordListTail = pNew;
1087   } else {
1088     mIfrRecordListTail->mNext = pNew;
1089     mIfrRecordListTail = pNew;
1090   }
1091   mRecordCount++;
1092 
1093   return mRecordCount;
1094 }
1095 
1096 VOID
IfrRecordInfoUpdate(IN UINT32 RecordIdx,IN UINT32 LineNo,IN CHAR8 * BinBuf,IN UINT8 BinBufLen,IN UINT32 Offset)1097 CIfrRecordInfoDB::IfrRecordInfoUpdate (
1098   IN UINT32 RecordIdx,
1099   IN UINT32 LineNo,
1100   IN CHAR8  *BinBuf,
1101   IN UINT8  BinBufLen,
1102   IN UINT32 Offset
1103   )
1104 {
1105   SIfrRecord *pNode;
1106   SIfrRecord *Prev;
1107 
1108   if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {
1109     return;
1110   }
1111 
1112   if (LineNo == 0) {
1113     //
1114     // Line number is not specified explicitly, try to use line number of previous opcode
1115     //
1116     Prev = GetRecordInfoFromIdx (RecordIdx - 1);
1117     if (Prev != NULL) {
1118       LineNo = Prev->mLineNo;
1119     }
1120   }
1121 
1122   pNode->mLineNo    = LineNo;
1123   pNode->mOffset    = Offset;
1124   pNode->mBinBufLen = BinBufLen;
1125   pNode->mIfrBinBuf = BinBuf;
1126 
1127 }
1128 
1129 VOID
IfrRecordOutput(OUT PACKAGE_DATA & TBuffer)1130 CIfrRecordInfoDB::IfrRecordOutput (
1131   OUT PACKAGE_DATA &TBuffer
1132   )
1133 {
1134   CHAR8      *Temp;
1135   SIfrRecord *pNode;
1136 
1137   if (TBuffer.Buffer != NULL) {
1138     delete[] TBuffer.Buffer;
1139   }
1140 
1141   TBuffer.Size = 0;
1142   TBuffer.Buffer = NULL;
1143 
1144 
1145   if (mSwitch == FALSE) {
1146     return;
1147   }
1148 
1149   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1150     TBuffer.Size += pNode->mBinBufLen;
1151   }
1152 
1153   if (TBuffer.Size != 0) {
1154     TBuffer.Buffer = new CHAR8[TBuffer.Size];
1155   } else {
1156     return;
1157   }
1158 
1159   Temp = TBuffer.Buffer;
1160 
1161   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1162     if (pNode->mIfrBinBuf != NULL) {
1163       memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen);
1164       Temp += pNode->mBinBufLen;
1165     }
1166   }
1167 
1168   return;
1169 }
1170 
1171 VOID
IfrRecordOutput(IN FILE * File,IN UINT32 LineNo)1172 CIfrRecordInfoDB::IfrRecordOutput (
1173   IN FILE   *File,
1174   IN UINT32 LineNo
1175   )
1176 {
1177   SIfrRecord *pNode;
1178   UINT8      Index;
1179   UINT32     TotalSize;
1180 
1181   if (mSwitch == FALSE) {
1182     return;
1183   }
1184 
1185   if (File == NULL) {
1186     return;
1187   }
1188 
1189   TotalSize = 0;
1190 
1191   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1192     if (pNode->mLineNo == LineNo || LineNo == 0) {
1193       fprintf (File, ">%08X: ", pNode->mOffset);
1194       TotalSize += pNode->mBinBufLen;
1195       if (pNode->mIfrBinBuf != NULL) {
1196         for (Index = 0; Index < pNode->mBinBufLen; Index++) {
1197           fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));
1198         }
1199       }
1200       fprintf (File, "\n");
1201     }
1202   }
1203 
1204   if (LineNo == 0) {
1205     fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize);
1206   }
1207 }
1208 
1209 //
1210 // for framework vfr file
1211 // adjust opcode sequence for uefi IFR format
1212 // adjust inconsistent and varstore into the right position.
1213 //
1214 BOOLEAN
CheckQuestionOpCode(IN UINT8 OpCode)1215 CIfrRecordInfoDB::CheckQuestionOpCode (
1216   IN UINT8 OpCode
1217   )
1218 {
1219   switch (OpCode) {
1220   case EFI_IFR_CHECKBOX_OP:
1221   case EFI_IFR_NUMERIC_OP:
1222   case EFI_IFR_PASSWORD_OP:
1223   case EFI_IFR_ONE_OF_OP:
1224   case EFI_IFR_ACTION_OP:
1225   case EFI_IFR_STRING_OP:
1226   case EFI_IFR_DATE_OP:
1227   case EFI_IFR_TIME_OP:
1228   case EFI_IFR_ORDERED_LIST_OP:
1229   case EFI_IFR_REF_OP:
1230     return TRUE;
1231   default:
1232     return FALSE;
1233   }
1234 }
1235 
1236 BOOLEAN
CheckIdOpCode(IN UINT8 OpCode)1237 CIfrRecordInfoDB::CheckIdOpCode (
1238   IN UINT8 OpCode
1239   )
1240 {
1241   switch (OpCode) {
1242   case EFI_IFR_EQ_ID_VAL_OP:
1243   case EFI_IFR_EQ_ID_ID_OP:
1244   case EFI_IFR_EQ_ID_VAL_LIST_OP:
1245   case EFI_IFR_QUESTION_REF1_OP:
1246     return TRUE;
1247   default:
1248     return FALSE;
1249   }
1250 }
1251 
1252 EFI_QUESTION_ID
GetOpcodeQuestionId(IN EFI_IFR_OP_HEADER * OpHead)1253 CIfrRecordInfoDB::GetOpcodeQuestionId (
1254   IN EFI_IFR_OP_HEADER *OpHead
1255   )
1256 {
1257   EFI_IFR_QUESTION_HEADER *QuestionHead;
1258 
1259   QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1);
1260 
1261   return QuestionHead->QuestionId;
1262 }
1263 
1264 SIfrRecord *
GetRecordInfoFromOffset(IN UINT32 Offset)1265 CIfrRecordInfoDB::GetRecordInfoFromOffset (
1266   IN UINT32 Offset
1267   )
1268 {
1269   SIfrRecord *pNode = NULL;
1270 
1271   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1272     if (pNode->mOffset == Offset) {
1273       return pNode;
1274     }
1275   }
1276 
1277   return pNode;
1278 }
1279 
1280 /**
1281   Add just the op code position.
1282 
1283   Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,
1284   so pDynamicOpcodeNodes is before mIfrRecordListTail.
1285 
1286   From
1287 
1288   |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|
1289 
1290   To
1291 
1292   |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|
1293 
1294   Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,
1295   so new records are appennded to the end of OriginalIfrRecordListTail.
1296 
1297   From
1298 
1299   |mIfrRecordListHead + ...+ pAdjustNode +  ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|
1300 
1301   To
1302 
1303   |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode +  ... + OriginalIfrRecordListTail|
1304 
1305 
1306   @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.
1307 
1308 **/
1309 BOOLEAN
IfrAdjustDynamicOpcodeInRecords(IN BOOLEAN CreateOpcodeAfterParsingVfr)1310 CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (
1311   IN BOOLEAN  CreateOpcodeAfterParsingVfr
1312   )
1313 {
1314   UINT32             OpcodeOffset;
1315   SIfrRecord         *pNode, *pPreNode;
1316   SIfrRecord         *pAdjustNode, *pNodeBeforeAdjust;
1317   SIfrRecord         *pNodeBeforeDynamic;
1318 
1319   pPreNode            = NULL;
1320   pAdjustNode         = NULL;
1321   pNodeBeforeDynamic  = NULL;
1322   OpcodeOffset        = 0;
1323 
1324   //
1325   // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,
1326   // and the node before pDynamicOpcodeNode.
1327   //
1328   for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {
1329     if (OpcodeOffset == gAdjustOpcodeOffset) {
1330       pAdjustNode       = pNode;
1331       pNodeBeforeAdjust = pPreNode;
1332     } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {
1333       pNodeBeforeDynamic = pPreNode;
1334     }
1335     if (pNode->mNext != NULL) {
1336       pPreNode = pNode;
1337     }
1338     OpcodeOffset += pNode->mBinBufLen;
1339   }
1340 
1341   //
1342   // Check the nodes whether exist.
1343   //
1344   if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL || pNodeBeforeAdjust == NULL) {
1345     return FALSE;
1346   }
1347 
1348   //
1349   // Adjust the node. pPreNode save the Node before mIfrRecordListTail
1350   //
1351   pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext;
1352   if (CreateOpcodeAfterParsingVfr) {
1353     //
1354     // mIfrRecordListTail is the end of pDynamicNode (Case2).
1355     //
1356     mIfrRecordListTail->mNext = pAdjustNode;
1357     mIfrRecordListTail = pNodeBeforeDynamic;
1358     mIfrRecordListTail->mNext = NULL;
1359   } else {
1360     //
1361     //pPreNode is the end of pDynamicNode(Case1).
1362     //
1363     pPreNode->mNext = pAdjustNode;
1364     pNodeBeforeDynamic->mNext = mIfrRecordListTail;
1365   }
1366 
1367   return TRUE;
1368 }
1369 
1370 /**
1371   Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.
1372 
1373   @param CreateOpcodeAfterParsingVfr     Whether create the dynamic opcode after parsing the VFR file.
1374 
1375 **/
1376 VOID
IfrUpdateRecordInfoForDynamicOpcode(IN BOOLEAN CreateOpcodeAfterParsingVfr)1377 CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (
1378   IN BOOLEAN  CreateOpcodeAfterParsingVfr
1379   )
1380 {
1381   SIfrRecord          *pRecord;
1382 
1383   //
1384   // Base on the original offset info to update the record list.
1385   //
1386   if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) {
1387     gCVfrErrorHandle.PrintMsg (0, (CHAR8 *)"Error", (CHAR8 *)"Can not find the adjust offset in the record.");
1388   }
1389 
1390   //
1391   // Base on the opcode binary length to recalculate the offset for each opcode.
1392   //
1393   IfrAdjustOffsetForRecord();
1394 
1395   //
1396   // Base on the offset to find the binary address.
1397   //
1398   pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset);
1399   while (pRecord != NULL) {
1400     pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);
1401     pRecord = pRecord->mNext;
1402   }
1403 }
1404 
1405 
1406 VOID
IfrAdjustOffsetForRecord(VOID)1407 CIfrRecordInfoDB::IfrAdjustOffsetForRecord (
1408   VOID
1409   )
1410 {
1411   UINT32             OpcodeOffset;
1412   SIfrRecord         *pNode;
1413 
1414   OpcodeOffset = 0;
1415   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1416     pNode->mOffset = OpcodeOffset;
1417     OpcodeOffset += pNode->mBinBufLen;
1418   }
1419 }
1420 
1421 EFI_VFR_RETURN_CODE
IfrRecordAdjust(VOID)1422 CIfrRecordInfoDB::IfrRecordAdjust (
1423   VOID
1424   )
1425 {
1426   SIfrRecord *pNode, *preNode;
1427   SIfrRecord *uNode, *tNode;
1428   EFI_IFR_OP_HEADER  *OpHead, *tOpHead;
1429   EFI_QUESTION_ID    QuestionId;
1430   UINT32             StackCount;
1431   UINT32             QuestionScope;
1432   CHAR8              ErrorMsg[MAX_STRING_LEN] = {0, };
1433   EFI_VFR_RETURN_CODE  Status;
1434 
1435   //
1436   // Init local variable
1437   //
1438   Status = VFR_RETURN_SUCCESS;
1439   pNode = mIfrRecordListHead;
1440   preNode = pNode;
1441   QuestionScope = 0;
1442   while (pNode != NULL) {
1443     OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
1444 
1445     //
1446     // make sure the inconsistent opcode in question scope
1447     //
1448     if (QuestionScope > 0) {
1449       QuestionScope += OpHead->Scope;
1450       if (OpHead->OpCode == EFI_IFR_END_OP) {
1451         QuestionScope --;
1452       }
1453     }
1454 
1455     if (CheckQuestionOpCode (OpHead->OpCode)) {
1456       QuestionScope = 1;
1457     }
1458     //
1459     // for the inconsistent opcode not in question scope, adjust it
1460     //
1461     if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) {
1462       //
1463       // for inconsistent opcode not in question scope
1464       //
1465 
1466       //
1467       // Count inconsistent opcode Scope
1468       //
1469       StackCount = OpHead->Scope;
1470       QuestionId = EFI_QUESTION_ID_INVALID;
1471       tNode = pNode;
1472       while (tNode != NULL && StackCount > 0) {
1473         tNode = tNode->mNext;
1474         tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf;
1475         //
1476         // Calculate Scope Number
1477         //
1478         StackCount += tOpHead->Scope;
1479         if (tOpHead->OpCode == EFI_IFR_END_OP) {
1480           StackCount --;
1481         }
1482         //
1483         // by IdEqual opcode to get QuestionId
1484         //
1485         if (QuestionId == EFI_QUESTION_ID_INVALID &&
1486             CheckIdOpCode (tOpHead->OpCode)) {
1487           QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1);
1488         }
1489       }
1490       if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) {
1491         //
1492         // report error; not found
1493         //
1494         sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId);
1495         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
1496         Status = VFR_RETURN_MISMATCHED;
1497         break;
1498       }
1499       //
1500       // extract inconsistent opcode list
1501       // pNode is Inconsistent opcode, tNode is End Opcode
1502       //
1503 
1504       //
1505       // insert inconsistent opcode list into the right question scope by questionid
1506       //
1507       for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) {
1508         tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf;
1509         if (CheckQuestionOpCode (tOpHead->OpCode) &&
1510             (QuestionId == GetOpcodeQuestionId (tOpHead))) {
1511           break;
1512         }
1513       }
1514       //
1515       // insert inconsistent opcode list and check LATE_CHECK flag
1516       //
1517       if (uNode != NULL) {
1518         if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) {
1519           //
1520           // if LATE_CHECK flag is set, change inconsistent to nosumbit
1521           //
1522           OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP;
1523         }
1524 
1525         //
1526         // skip the default storage for Date and Time
1527         //
1528         if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) {
1529           uNode = uNode->mNext;
1530         }
1531 
1532         preNode->mNext = tNode->mNext;
1533         tNode->mNext = uNode->mNext;
1534         uNode->mNext = pNode;
1535         //
1536         // reset pNode to head list, scan the whole list again.
1537         //
1538         pNode = mIfrRecordListHead;
1539         preNode = pNode;
1540         QuestionScope = 0;
1541         continue;
1542       } else {
1543         //
1544         // not found matched question id, report error
1545         //
1546         sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId);
1547         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
1548         Status = VFR_RETURN_MISMATCHED;
1549         break;
1550       }
1551     } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP ||
1552                OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) {
1553       //
1554       // for new added group of varstore opcode
1555       //
1556       tNode = pNode;
1557       while (tNode->mNext != NULL) {
1558         tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf;
1559         if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP &&
1560             tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) {
1561           break;
1562         }
1563         tNode = tNode->mNext;
1564       }
1565 
1566       if (tNode->mNext == NULL) {
1567         //
1568         // invalid IfrCode, IfrCode end by EndOpCode
1569         //
1570         gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end");
1571         Status = VFR_RETURN_MISMATCHED;
1572         break;
1573       }
1574 
1575       if (tOpHead->OpCode != EFI_IFR_END_OP) {
1576           //
1577           // not new added varstore, which are not needed to be adjust.
1578           //
1579           preNode = tNode;
1580           pNode   = tNode->mNext;
1581           continue;
1582       } else {
1583         //
1584         // move new added varstore opcode to the position befor form opcode
1585         // varstore opcode between pNode and tNode
1586         //
1587 
1588         //
1589         // search form opcode from begin
1590         //
1591         for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) {
1592           tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf;
1593           if (tOpHead->OpCode == EFI_IFR_FORM_OP) {
1594             break;
1595           }
1596         }
1597         //
1598         // Insert varstore opcode beform form opcode if form opcode is found
1599         //
1600         if (uNode->mNext != NULL) {
1601           preNode->mNext = tNode->mNext;
1602           tNode->mNext = uNode->mNext;
1603           uNode->mNext = pNode;
1604           //
1605           // reset pNode to head list, scan the whole list again.
1606           //
1607           pNode = mIfrRecordListHead;
1608           preNode = pNode;
1609           QuestionScope = 0;
1610           continue;
1611         } else {
1612           //
1613           // not found form, continue scan IfrRecord list
1614           //
1615           preNode = tNode;
1616           pNode   = tNode->mNext;
1617           continue;
1618         }
1619       }
1620     }
1621     //
1622     // next node
1623     //
1624     preNode = pNode;
1625     pNode = pNode->mNext;
1626   }
1627 
1628   //
1629   // Update Ifr Opcode Offset
1630   //
1631   if (Status == VFR_RETURN_SUCCESS) {
1632     IfrAdjustOffsetForRecord ();
1633   }
1634   return Status;
1635 }
1636 
1637 /**
1638   When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not
1639   given by expression, should save the default info for the Buffer VarStore.
1640 
1641   @param  DefaultId           The default id.
1642   @param  pQuestionNode       Point to the question opcode node.
1643   @param  Value               The default value.
1644 **/
1645 VOID
IfrAddDefaultToBufferConfig(IN UINT16 DefaultId,IN SIfrRecord * pQuestionNode,IN EFI_IFR_TYPE_VALUE Value)1646 CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (
1647   IN  UINT16                  DefaultId,
1648   IN  SIfrRecord              *pQuestionNode,
1649   IN  EFI_IFR_TYPE_VALUE      Value
1650   )
1651 {
1652   CHAR8                   *VarStoreName = NULL;
1653   EFI_VFR_VARSTORE_TYPE    VarStoreType  = EFI_VFR_VARSTORE_INVALID;
1654   EFI_GUID                 *VarGuid      = NULL;
1655   EFI_VARSTORE_INFO        VarInfo;
1656   EFI_IFR_QUESTION_HEADER  *QuestionHead;
1657   EFI_IFR_OP_HEADER        *pQuestionOpHead;
1658 
1659   pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
1660   QuestionHead    = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1);
1661 
1662   //
1663   // Get the Var Store name and type.
1664   //
1665   gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName);
1666   VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId);
1667   VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId);
1668 
1669   //
1670   // Only for Buffer storage need to save the default info in the storage.
1671   // Other type storage, just return.
1672   //
1673   if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) {
1674     return;
1675   } else {
1676     VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset;
1677     VarInfo.mVarStoreId = QuestionHead->VarStoreId;
1678   }
1679 
1680   //
1681   // Get the buffer storage info about this question.
1682   //
1683   gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo);
1684 
1685   //
1686   // Add action.
1687   //
1688   gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
1689     DefaultId,
1690     VarInfo,
1691     VarStoreName,
1692     VarGuid,
1693     VarInfo.mVarType,
1694     Value
1695     );
1696 }
1697 
1698 /**
1699   Record the number and default id of all defaultstore opcode.
1700 
1701 **/
1702 VOID
IfrGetDefaultStoreInfo(VOID)1703 CIfrRecordInfoDB::IfrGetDefaultStoreInfo (
1704   VOID
1705   )
1706 {
1707   SIfrRecord             *pNode;
1708   EFI_IFR_OP_HEADER      *pOpHead;
1709   EFI_IFR_DEFAULTSTORE   *DefaultStore;
1710 
1711   pNode                = mIfrRecordListHead;
1712   mAllDefaultTypeCount = 0;
1713 
1714   while (pNode != NULL) {
1715     pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
1716 
1717     if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){
1718       DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf;
1719       mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId;
1720     }
1721     pNode = pNode->mNext;
1722   }
1723 }
1724 
1725 /**
1726   Create new default opcode record.
1727 
1728   @param    Size            The new default opcode size.
1729   @param    DefaultId       The new default id.
1730   @param    Type            The new default type.
1731   @param    LineNo          The line number of the new record.
1732   @param    Value           The new default value.
1733 
1734 **/
1735 VOID
IfrCreateDefaultRecord(IN UINT8 Size,IN UINT16 DefaultId,IN UINT8 Type,IN UINT32 LineNo,IN EFI_IFR_TYPE_VALUE Value)1736 CIfrRecordInfoDB::IfrCreateDefaultRecord(
1737   IN UINT8               Size,
1738   IN UINT16              DefaultId,
1739   IN UINT8               Type,
1740   IN UINT32              LineNo,
1741   IN EFI_IFR_TYPE_VALUE  Value
1742   )
1743 {
1744   CIfrDefault   *DObj;
1745   CIfrDefault2  *DObj2;
1746 
1747   DObj  = NULL;
1748   DObj2 = NULL;
1749 
1750   if (Type == EFI_IFR_TYPE_OTHER) {
1751     DObj2 = new CIfrDefault2 (Size);
1752     DObj2->SetDefaultId(DefaultId);
1753     DObj2->SetType(Type);
1754     DObj2->SetLineNo(LineNo);
1755     DObj2->SetScope (1);
1756     delete DObj2;
1757   } else {
1758     DObj = new CIfrDefault (Size);
1759     DObj->SetDefaultId(DefaultId);
1760     DObj->SetType(Type);
1761     DObj->SetLineNo(LineNo);
1762     DObj->SetValue (Value);
1763     delete DObj;
1764   }
1765 }
1766 
1767 /**
1768   Create new default opcode for question base on the QuestionDefaultInfo.
1769 
1770   @param  pQuestionNode              Point to the question opcode Node.
1771   @param  QuestionDefaultInfo        Point to the QuestionDefaultInfo for current question.
1772 
1773 **/
1774 VOID
IfrCreateDefaultForQuestion(IN SIfrRecord * pQuestionNode,IN QuestionDefaultRecord * QuestionDefaultInfo)1775 CIfrRecordInfoDB::IfrCreateDefaultForQuestion (
1776   IN  SIfrRecord              *pQuestionNode,
1777   IN  QuestionDefaultRecord   *QuestionDefaultInfo
1778   )
1779 {
1780   EFI_IFR_OP_HEADER      *pOpHead;
1781   EFI_IFR_DEFAULT        *Default;
1782   SIfrRecord             *pSNode;
1783   SIfrRecord             *pENode;
1784   SIfrRecord             *pDefaultNode;
1785   CIfrObj                *Obj;
1786   CHAR8                  *ObjBinBuf;
1787   UINT8                  ScopeCount;
1788   UINT8                  OpcodeNumber;
1789   UINT8                  OpcodeCount;
1790   UINT8                  DefaultSize;
1791   EFI_IFR_ONE_OF_OPTION  *DefaultOptionOpcode;
1792   EFI_IFR_TYPE_VALUE     CheckBoxDefaultValue;
1793 
1794   CheckBoxDefaultValue.b = 1;
1795   pOpHead                = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
1796   ScopeCount             = 0;
1797   OpcodeCount            = 0;
1798   Obj                    = NULL;
1799 
1800   //
1801   // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1802   //
1803   gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset;
1804   //
1805   // Case 1:
1806   // For oneof, the default with smallest default id is given by the option flag.
1807   // So create the missing defaults base on the oneof option value(mDefaultValueRecord).
1808   //
1809   if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
1810     DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf;
1811     DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value);
1812     DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value);
1813     for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
1814       if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
1815         IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value);
1816         //
1817         // Save the new created default in the buffer storage.
1818         //
1819         IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value);
1820       }
1821     }
1822     return;
1823   }
1824 
1825   //
1826   // Case2:
1827   // For checkbox, the default with smallest default id is given by the question flag.
1828   // And create the missing defaults with true value.
1829   //
1830   if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
1831     DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN);
1832     for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
1833       if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
1834         IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue);
1835         //
1836         // Save the new created default.
1837         //
1838         IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue);
1839       }
1840     }
1841     return;
1842   }
1843 
1844   //
1845   // Case3:
1846   // The default with smallest default id is given by the default opcode.
1847   // So create the missing defaults base on the value in the default opcode.
1848   //
1849 
1850   //
1851   // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.
1852   //
1853   pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord;
1854   Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf;
1855   //
1856   // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1857   //
1858   gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset;
1859 
1860   if (Default->Type == EFI_IFR_TYPE_OTHER) {
1861     //
1862     // EFI_IFR_DEFAULT_2 opcode.
1863     //
1864     // Point to the first expression opcode.
1865     //
1866     pSNode = pDefaultNode->mNext;
1867     pENode = NULL;
1868     ScopeCount++;
1869     //
1870     // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)
1871     //
1872     while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) {
1873       pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
1874       if (pOpHead->Scope == 1) {
1875         ScopeCount++;
1876       }
1877       if (pOpHead->OpCode == EFI_IFR_END_OP) {
1878         ScopeCount--;
1879       }
1880       pENode = pSNode;
1881       pSNode = pSNode->mNext;
1882       OpcodeCount++;
1883     }
1884 
1885     assert (pSNode);
1886     assert (pENode);
1887 
1888     //
1889     // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1890     //
1891     gAdjustOpcodeOffset = pSNode->mOffset;
1892     //
1893     // Create new default opcode node for missing default.
1894     //
1895     for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
1896       OpcodeNumber = OpcodeCount;
1897       if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
1898         IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value);
1899         //
1900         // Point to the first expression opcode node.
1901         //
1902         pSNode = pDefaultNode->mNext;
1903         //
1904         // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.
1905         //
1906         while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) {
1907           pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
1908           Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);
1909           assert (Obj != NULL);
1910           Obj->SetLineNo (pSNode->mLineNo);
1911           ObjBinBuf = Obj->GetObjBinAddr<CHAR8>();
1912           memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);
1913           delete Obj;
1914           pSNode = pSNode->mNext;
1915         }
1916       }
1917     }
1918   } else {
1919     //
1920     // EFI_IFR_DEFAULT opcode.
1921     //
1922     // Create new default opcode node for missing default.
1923     //
1924     for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
1925       if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
1926         IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value);
1927         //
1928         // Save the new created default in the buffer storage..
1929         //
1930         IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value);
1931       }
1932     }
1933   }
1934 }
1935 
1936 /**
1937   Parse the default information in a question, get the QuestionDefaultInfo.
1938 
1939   @param  pQuestionNode          Point to the question record Node.
1940   @param  QuestionDefaultInfo    On return, point to the QuestionDefaultInfo.
1941 **/
1942 VOID
IfrParseDefaulInfoInQuestion(IN SIfrRecord * pQuestionNode,OUT QuestionDefaultRecord * QuestionDefaultInfo)1943 CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(
1944   IN  SIfrRecord              *pQuestionNode,
1945   OUT QuestionDefaultRecord   *QuestionDefaultInfo
1946   )
1947 {
1948   SIfrRecord              *pSNode;
1949   EFI_IFR_ONE_OF_OPTION   *OneofOptionOpcode;
1950   EFI_IFR_OP_HEADER       *pSOpHead;
1951   EFI_IFR_CHECKBOX        *CheckBoxOpcode;
1952   EFI_IFR_DEFAULT         *DefaultOpcode;
1953   BOOLEAN                 IsOneOfOpcode;
1954   UINT16                  SmallestDefaultId;
1955   UINT8                   ScopeCount;
1956 
1957   SmallestDefaultId  = 0xffff;
1958   IsOneOfOpcode      = FALSE;
1959   ScopeCount         = 0;
1960   pSNode             = pQuestionNode;
1961 
1962   //
1963   // Parse all the opcodes in the Question.
1964   //
1965   while (pSNode != NULL) {
1966     pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
1967     //
1968     // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.
1969     // Scopes may be nested within other scopes.
1970     // When finishing parsing a question, the scope count must be zero.
1971     //
1972     if (pSOpHead->Scope == 1) {
1973       ScopeCount++;
1974     }
1975     if (pSOpHead->OpCode == EFI_IFR_END_OP) {
1976       ScopeCount--;
1977     }
1978     //
1979     // Check whether finishing parsing a question.
1980     //
1981     if (ScopeCount == 0) {
1982       break;
1983     }
1984 
1985     //
1986     // Record the default information in the question.
1987     //
1988     switch (pSOpHead->OpCode) {
1989     case EFI_IFR_ONE_OF_OP:
1990       IsOneOfOpcode = TRUE;
1991       break;
1992     case EFI_IFR_CHECKBOX_OP:
1993       //
1994       // The default info of check box may be given by flag.
1995       // So need to check the flag of check box.
1996       //
1997       CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf;
1998       if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) {
1999         //
2000         // Check whether need to update the smallest default id.
2001         //
2002         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
2003           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2004         }
2005         //
2006         // Update the QuestionDefaultInfo.
2007         //
2008         for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
2009           if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
2010             if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
2011               QuestionDefaultInfo->mDefaultNumber ++;
2012               QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
2013             }
2014             break;
2015           }
2016         }
2017       }
2018       if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) {
2019         //
2020         // Check whether need to update the smallest default id.
2021         //
2022         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2023           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2024         }
2025         //
2026         // Update the QuestionDefaultInfo.
2027         //
2028         for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
2029           if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2030             if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
2031               QuestionDefaultInfo->mDefaultNumber ++;
2032               QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
2033             }
2034             break;
2035           }
2036         }
2037       }
2038       break;
2039     case EFI_IFR_ONE_OF_OPTION_OP:
2040       if (!IsOneOfOpcode) {
2041         //
2042         // Only check the option in oneof.
2043         //
2044         break;
2045       }
2046       OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf;
2047       if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
2048         //
2049         // The option is used as the standard default.
2050         // Check whether need to update the smallest default id and QuestionDefaultInfo.
2051         //
2052         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
2053           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2054           QuestionDefaultInfo->mDefaultValueRecord = pSNode;
2055         }
2056         //
2057         // Update the IsDefaultIdExist array in QuestionDefaultInfo.
2058         //
2059         for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
2060           if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
2061             if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
2062               QuestionDefaultInfo->mDefaultNumber ++;
2063               QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
2064             }
2065             break;
2066           }
2067         }
2068       }
2069       if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) {
2070         //
2071         // This option is used as the manufacture default.
2072         // Check whether need to update the smallest default id and QuestionDefaultInfo.
2073         //
2074         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2075           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2076           QuestionDefaultInfo->mDefaultValueRecord = pSNode;
2077         }
2078         //
2079         // Update the QuestionDefaultInfo.
2080         //
2081         for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
2082           if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2083             if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
2084               QuestionDefaultInfo->mDefaultNumber ++;
2085               QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
2086             }
2087             break;
2088           }
2089         }
2090       }
2091       break;
2092     case EFI_IFR_DEFAULT_OP:
2093       DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf;
2094       //
2095       // Check whether need to update the smallest default id and QuestionDefaultInfo.
2096       //
2097       if (SmallestDefaultId >= DefaultOpcode->DefaultId ) {
2098         SmallestDefaultId = DefaultOpcode->DefaultId;
2099         QuestionDefaultInfo->mDefaultValueRecord= pSNode;
2100         QuestionDefaultInfo->mIsDefaultOpcode= TRUE;
2101       }
2102       //
2103       // Update the QuestionDefaultInfo.
2104       //
2105       for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){
2106         if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) {
2107           if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
2108             QuestionDefaultInfo->mDefaultNumber ++;
2109             QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
2110           }
2111           break;
2112         }
2113       }
2114       break;
2115     default:
2116       break;
2117     }
2118     //
2119     // Parse next opcode in this question.
2120     //
2121     pSNode = pSNode->mNext;
2122   }
2123 }
2124 
2125 /**
2126   Check or add default for question if need.
2127 
2128   This function will check the default info for question.
2129   If the question has default, but the default number < defaultstore opcode number.
2130   will do following two action :
2131 
2132   1. if (AutoDefault) will add default for question to support all kinds of defaults.
2133   2. if (CheckDefault) will generate an error to tell user the question misses some default value.
2134 
2135   We assume that the two options can not be TRUE at same time.
2136   If they are TRUE at same time, only do the action corresponding to AutoDefault option.
2137 
2138   @param  AutoDefault          Add default for question if needed
2139   @param  CheckDefault         Check the default info, if missing default, generates an error.
2140 
2141 **/
2142 VOID
IfrCheckAddDefaultRecord(BOOLEAN AutoDefault,BOOLEAN CheckDefault)2143 CIfrRecordInfoDB::IfrCheckAddDefaultRecord (
2144   BOOLEAN  AutoDefault,
2145   BOOLEAN  CheckDefault
2146   )
2147 {
2148   SIfrRecord            *pNode;
2149   SIfrRecord            *pTailNode;
2150   SIfrRecord            *pStartAdjustNode;
2151   EFI_IFR_OP_HEADER     *pOpHead;
2152   QuestionDefaultRecord  QuestionDefaultInfo;
2153   UINT8                  MissingDefaultCount;
2154   CHAR8                  Msg[MAX_STRING_LEN] = {0, };
2155 
2156   pNode               = mIfrRecordListHead;
2157 
2158   //
2159   // Record the number and default id of all defaultstore opcode.
2160   //
2161   IfrGetDefaultStoreInfo ();
2162 
2163   while (pNode != NULL) {
2164     pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
2165     //
2166     // Check whether is question opcode.
2167     //
2168     if (CheckQuestionOpCode (pOpHead->OpCode)) {
2169       //
2170       // Initialize some local variables here, because they vary with question.
2171       // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.
2172       //
2173       memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord));
2174       pTailNode = mIfrRecordListTail;
2175       //
2176       // Get the QuestionDefaultInfo for current question.
2177       //
2178       IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo);
2179 
2180       if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) {
2181         if (AutoDefault) {
2182           //
2183           // Create default for question which misses default.
2184           //
2185           IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo);
2186 
2187           //
2188           // Adjust the buffer content.
2189           // pStartAdjustNode->mIfrBinBuf points to the insert position.
2190           // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.
2191           //
2192           pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset);
2193           gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE);
2194 
2195           //
2196           // Update the record info.
2197           //
2198           IfrUpdateRecordInfoForDynamicOpcode (TRUE);
2199         } else if (CheckDefault) {
2200           //
2201           // Generate an error for question which misses default.
2202           //
2203           MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber;
2204           sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode);
2205           gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg);
2206         }
2207       }
2208     }
2209     //
2210     // parse next opcode.
2211     //
2212     pNode = pNode->mNext;
2213   }
2214 }
2215 
2216 CIfrRecordInfoDB gCIfrRecordInfoDB;
2217 
2218 VOID
_EMIT_PENDING_OBJ(VOID)2219 CIfrObj::_EMIT_PENDING_OBJ (
2220   VOID
2221   )
2222 {
2223   CHAR8  *ObjBinBuf = NULL;
2224 
2225   //
2226   // do nothing
2227   //
2228   if (!mDelayEmit || !gCreateOp) {
2229     return;
2230   }
2231 
2232   mPkgOffset = gCFormPkg.GetPkgLength ();
2233   //
2234   // update data buffer to package data
2235   //
2236   ObjBinBuf  = gCFormPkg.IfrBinBufferGet (mObjBinLen);
2237   if (ObjBinBuf != NULL) {
2238     memmove (ObjBinBuf, mObjBinBuf, mObjBinLen);
2239   }
2240 
2241   //
2242   // update bin buffer to package data buffer
2243   //
2244   if (mObjBinBuf != NULL) {
2245     delete[] mObjBinBuf;
2246     mObjBinBuf = ObjBinBuf;
2247   }
2248 
2249   mDelayEmit = FALSE;
2250 }
2251 
2252 /*
2253  * The definition of CIfrObj's member function
2254  */
2255 static struct {
2256   UINT8  mSize;
2257   UINT8  mScope;
2258 } gOpcodeSizesScopeTable[] = {
2259   { 0, 0 },                                    // EFI_IFR_INVALID - 0x00
2260   { sizeof (EFI_IFR_FORM), 1 },                // EFI_IFR_FORM_OP
2261   { sizeof (EFI_IFR_SUBTITLE), 1 },            // EFI_IFR_SUBTITLE_OP
2262   { sizeof (EFI_IFR_TEXT), 0 },                // EFI_IFR_TEXT_OP
2263   { sizeof (EFI_IFR_IMAGE), 0 },               // EFI_IFR_IMAGE_OP
2264   { sizeof (EFI_IFR_ONE_OF), 1 },              // EFI_IFR_ONE_OF_OP - 0x05
2265   { sizeof (EFI_IFR_CHECKBOX), 1},             // EFI_IFR_CHECKBOX_OP
2266   { sizeof (EFI_IFR_NUMERIC), 1 },             // EFI_IFR_NUMERIC_OP
2267   { sizeof (EFI_IFR_PASSWORD), 1 },            // EFI_IFR_PASSWORD_OP
2268   { sizeof (EFI_IFR_ONE_OF_OPTION), 0 },       // EFI_IFR_ONE_OF_OPTION_OP
2269   { sizeof (EFI_IFR_SUPPRESS_IF), 1 },         // EFI_IFR_SUPPRESS_IF - 0x0A
2270   { sizeof (EFI_IFR_LOCKED), 0 },              // EFI_IFR_LOCKED_OP
2271   { sizeof (EFI_IFR_ACTION), 1 },              // EFI_IFR_ACTION_OP
2272   { sizeof (EFI_IFR_RESET_BUTTON), 1 },        // EFI_IFR_RESET_BUTTON_OP
2273   { sizeof (EFI_IFR_FORM_SET), 1 },            // EFI_IFR_FORM_SET_OP -0xE
2274   { sizeof (EFI_IFR_REF), 0 },                 // EFI_IFR_REF_OP
2275   { sizeof (EFI_IFR_NO_SUBMIT_IF), 1},         // EFI_IFR_NO_SUBMIT_IF_OP -0x10
2276   { sizeof (EFI_IFR_INCONSISTENT_IF), 1 },     // EFI_IFR_INCONSISTENT_IF_OP
2277   { sizeof (EFI_IFR_EQ_ID_VAL), 0 },           // EFI_IFR_EQ_ID_VAL_OP
2278   { sizeof (EFI_IFR_EQ_ID_ID), 0 },            // EFI_IFR_EQ_ID_ID_OP
2279   { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 },      // EFI_IFR_EQ_ID_LIST_OP - 0x14
2280   { sizeof (EFI_IFR_AND), 0 },                 // EFI_IFR_AND_OP
2281   { sizeof (EFI_IFR_OR), 0 },                  // EFI_IFR_OR_OP
2282   { sizeof (EFI_IFR_NOT), 0 },                 // EFI_IFR_NOT_OP
2283   { sizeof (EFI_IFR_RULE), 1 },                // EFI_IFR_RULE_OP
2284   { sizeof (EFI_IFR_GRAY_OUT_IF), 1 },         // EFI_IFR_GRAYOUT_IF_OP - 0x19
2285   { sizeof (EFI_IFR_DATE), 1 },                // EFI_IFR_DATE_OP
2286   { sizeof (EFI_IFR_TIME), 1 },                // EFI_IFR_TIME_OP
2287   { sizeof (EFI_IFR_STRING), 1 },              // EFI_IFR_STRING_OP
2288   { sizeof (EFI_IFR_REFRESH), 0 },             // EFI_IFR_REFRESH_OP
2289   { sizeof (EFI_IFR_DISABLE_IF), 1 },          // EFI_IFR_DISABLE_IF_OP - 0x1E
2290   { 0, 0 },                                    // 0x1F
2291   { sizeof (EFI_IFR_TO_LOWER), 0 },            // EFI_IFR_TO_LOWER_OP - 0x20
2292   { sizeof (EFI_IFR_TO_UPPER), 0 },            // EFI_IFR_TO_UPPER_OP - 0x21
2293   { sizeof (EFI_IFR_MAP), 1 },                 // EFI_IFR_MAP - 0x22
2294   { sizeof (EFI_IFR_ORDERED_LIST), 1 },        // EFI_IFR_ORDERED_LIST_OP - 0x23
2295   { sizeof (EFI_IFR_VARSTORE), 0 },            // EFI_IFR_VARSTORE_OP
2296   { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP
2297   { sizeof (EFI_IFR_VARSTORE_EFI), 0 },        // EFI_IFR_VARSTORE_EFI_OP
2298   { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 },     // EFI_IFR_VARSTORE_DEVICE_OP
2299   { sizeof (EFI_IFR_VERSION), 0 },             // EFI_IFR_VERSION_OP - 0x28
2300   { sizeof (EFI_IFR_END), 0 },                 // EFI_IFR_END_OP
2301   { sizeof (EFI_IFR_MATCH), 0 },               // EFI_IFR_MATCH_OP - 0x2A
2302   { sizeof (EFI_IFR_GET), 0 },                 // EFI_IFR_GET - 0x2B
2303   { sizeof (EFI_IFR_SET), 0 },                 // EFI_IFR_SET - 0x2C
2304   { sizeof (EFI_IFR_READ), 0 },                // EFI_IFR_READ - 0x2D
2305   { sizeof (EFI_IFR_WRITE), 0 },               // EFI_IFR_WRITE - 0x2E
2306   { sizeof (EFI_IFR_EQUAL), 0 },               // EFI_IFR_EQUAL_OP - 0x2F
2307   { sizeof (EFI_IFR_NOT_EQUAL), 0 },           // EFI_IFR_NOT_EQUAL_OP
2308   { sizeof (EFI_IFR_GREATER_THAN), 0 },        // EFI_IFR_GREATER_THAN_OP
2309   { sizeof (EFI_IFR_GREATER_EQUAL), 0 },       // EFI_IFR_GREATER_EQUAL_OP
2310   { sizeof (EFI_IFR_LESS_THAN), 0 },           // EFI_IFR_LESS_THAN_OP
2311   { sizeof (EFI_IFR_LESS_EQUAL), 0 },          // EFI_IFR_LESS_EQUAL_OP - 0x34
2312   { sizeof (EFI_IFR_BITWISE_AND), 0 },         // EFI_IFR_BITWISE_AND_OP
2313   { sizeof (EFI_IFR_BITWISE_OR), 0 },          // EFI_IFR_BITWISE_OR_OP
2314   { sizeof (EFI_IFR_BITWISE_NOT), 0 },         // EFI_IFR_BITWISE_NOT_OP
2315   { sizeof (EFI_IFR_SHIFT_LEFT), 0 },          // EFI_IFR_SHIFT_LEFT_OP
2316   { sizeof (EFI_IFR_SHIFT_RIGHT), 0 },         // EFI_IFR_SHIFT_RIGHT_OP
2317   { sizeof (EFI_IFR_ADD), 0 },                 // EFI_IFR_ADD_OP - 0x3A
2318   { sizeof (EFI_IFR_SUBTRACT), 0 },            // EFI_IFR_SUBTRACT_OP
2319   { sizeof (EFI_IFR_MULTIPLY), 0 },            // EFI_IFR_MULTIPLY_OP
2320   { sizeof (EFI_IFR_DIVIDE), 0 },              // EFI_IFR_DIVIDE_OP
2321   { sizeof (EFI_IFR_MODULO), 0 },              // EFI_IFR_MODULO_OP - 0x3E
2322   { sizeof (EFI_IFR_RULE_REF), 0 },            // EFI_IFR_RULE_REF_OP
2323   { sizeof (EFI_IFR_QUESTION_REF1), 0 },       // EFI_IFR_QUESTION_REF1_OP
2324   { sizeof (EFI_IFR_QUESTION_REF2), 0 },       // EFI_IFR_QUESTION_REF2_OP - 0x41
2325   { sizeof (EFI_IFR_UINT8), 0},                // EFI_IFR_UINT8
2326   { sizeof (EFI_IFR_UINT16), 0},               // EFI_IFR_UINT16
2327   { sizeof (EFI_IFR_UINT32), 0},               // EFI_IFR_UINT32
2328   { sizeof (EFI_IFR_UINT64), 0},               // EFI_IFR_UTNT64
2329   { sizeof (EFI_IFR_TRUE), 0 },                // EFI_IFR_TRUE_OP - 0x46
2330   { sizeof (EFI_IFR_FALSE), 0 },               // EFI_IFR_FALSE_OP
2331   { sizeof (EFI_IFR_TO_UINT), 0 },             // EFI_IFR_TO_UINT_OP
2332   { sizeof (EFI_IFR_TO_STRING), 0 },           // EFI_IFR_TO_STRING_OP
2333   { sizeof (EFI_IFR_TO_BOOLEAN), 0 },          // EFI_IFR_TO_BOOLEAN_OP
2334   { sizeof (EFI_IFR_MID), 0 },                 // EFI_IFR_MID_OP
2335   { sizeof (EFI_IFR_FIND), 0 },                // EFI_IFR_FIND_OP
2336   { sizeof (EFI_IFR_TOKEN), 0 },               // EFI_IFR_TOKEN_OP
2337   { sizeof (EFI_IFR_STRING_REF1), 0 },         // EFI_IFR_STRING_REF1_OP - 0x4E
2338   { sizeof (EFI_IFR_STRING_REF2), 0 },         // EFI_IFR_STRING_REF2_OP
2339   { sizeof (EFI_IFR_CONDITIONAL), 0 },         // EFI_IFR_CONDITIONAL_OP
2340   { sizeof (EFI_IFR_QUESTION_REF3), 0 },       // EFI_IFR_QUESTION_REF3_OP
2341   { sizeof (EFI_IFR_ZERO), 0 },                // EFI_IFR_ZERO_OP
2342   { sizeof (EFI_IFR_ONE), 0 },                 // EFI_IFR_ONE_OP
2343   { sizeof (EFI_IFR_ONES), 0 },                // EFI_IFR_ONES_OP
2344   { sizeof (EFI_IFR_UNDEFINED), 0 },           // EFI_IFR_UNDEFINED_OP
2345   { sizeof (EFI_IFR_LENGTH), 0 },              // EFI_IFR_LENGTH_OP
2346   { sizeof (EFI_IFR_DUP), 0 },                 // EFI_IFR_DUP_OP - 0x57
2347   { sizeof (EFI_IFR_THIS), 0 },                // EFI_IFR_THIS_OP
2348   { sizeof (EFI_IFR_SPAN), 0 },                // EFI_IFR_SPAN_OP
2349   { sizeof (EFI_IFR_VALUE), 1 },               // EFI_IFR_VALUE_OP
2350   { sizeof (EFI_IFR_DEFAULT), 0 },             // EFI_IFR_DEFAULT_OP
2351   { sizeof (EFI_IFR_DEFAULTSTORE), 0 },        // EFI_IFR_DEFAULTSTORE_OP - 0x5C
2352   { sizeof (EFI_IFR_FORM_MAP), 1},             // EFI_IFR_FORM_MAP_OP - 0x5D
2353   { sizeof (EFI_IFR_CATENATE), 0 },            // EFI_IFR_CATENATE_OP
2354   { sizeof (EFI_IFR_GUID), 0 },                // EFI_IFR_GUID_OP
2355   { sizeof (EFI_IFR_SECURITY), 0 },            // EFI_IFR_SECURITY_OP - 0x60
2356   { sizeof (EFI_IFR_MODAL_TAG), 0},            // EFI_IFR_MODAL_TAG_OP - 0x61
2357   { sizeof (EFI_IFR_REFRESH_ID), 0},           // EFI_IFR_REFRESH_ID_OP - 0x62
2358   { sizeof (EFI_IFR_WARNING_IF), 1},           // EFI_IFR_WARNING_IF_OP - 0x63
2359   { sizeof (EFI_IFR_MATCH2), 0 },              // EFI_IFR_MATCH2_OP - 0x64
2360 };
2361 
2362 #ifdef CIFROBJ_DEUBG
2363 static struct {
2364   CHAR8 *mIfrName;
2365 } gIfrObjPrintDebugTable[] = {
2366   "EFI_IFR_INVALID",    "EFI_IFR_FORM",                 "EFI_IFR_SUBTITLE",      "EFI_IFR_TEXT",            "EFI_IFR_IMAGE",         "EFI_IFR_ONE_OF",
2367   "EFI_IFR_CHECKBOX",   "EFI_IFR_NUMERIC",              "EFI_IFR_PASSWORD",      "EFI_IFR_ONE_OF_OPTION",   "EFI_IFR_SUPPRESS_IF",   "EFI_IFR_LOCKED",
2368   "EFI_IFR_ACTION",     "EFI_IFR_RESET_BUTTON",         "EFI_IFR_FORM_SET",      "EFI_IFR_REF",             "EFI_IFR_NO_SUBMIT_IF",  "EFI_IFR_INCONSISTENT_IF",
2369   "EFI_IFR_EQ_ID_VAL",  "EFI_IFR_EQ_ID_ID",             "EFI_IFR_EQ_ID_LIST",    "EFI_IFR_AND",             "EFI_IFR_OR",            "EFI_IFR_NOT",
2370   "EFI_IFR_RULE",       "EFI_IFR_GRAY_OUT_IF",          "EFI_IFR_DATE",          "EFI_IFR_TIME",            "EFI_IFR_STRING",        "EFI_IFR_REFRESH",
2371   "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID",              "EFI_IFR_TO_LOWER",      "EFI_IFR_TO_UPPER",        "EFI_IFR_MAP",           "EFI_IFR_ORDERED_LIST",
2372   "EFI_IFR_VARSTORE",   "EFI_IFR_VARSTORE_NAME_VALUE",  "EFI_IFR_VARSTORE_EFI",  "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION",       "EFI_IFR_END",
2373   "EFI_IFR_MATCH",      "EFI_IFR_GET",                  "EFI_IFR_SET",           "EFI_IFR_READ",            "EFI_IFR_WRITE",         "EFI_IFR_EQUAL",
2374   "EFI_IFR_NOT_EQUAL",  "EFI_IFR_GREATER_THAN",         "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN",       "EFI_IFR_LESS_EQUAL",    "EFI_IFR_BITWISE_AND",
2375   "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT",          "EFI_IFR_SHIFT_LEFT",    "EFI_IFR_SHIFT_RIGHT",     "EFI_IFR_ADD",           "EFI_IFR_SUBTRACT",
2376   "EFI_IFR_MULTIPLY",   "EFI_IFR_DIVIDE",               "EFI_IFR_MODULO",        "EFI_IFR_RULE_REF",        "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",
2377   "EFI_IFR_UINT8",      "EFI_IFR_UINT16",               "EFI_IFR_UINT32",        "EFI_IFR_UINT64",          "EFI_IFR_TRUE",          "EFI_IFR_FALSE",
2378   "EFI_IFR_TO_UINT",    "EFI_IFR_TO_STRING",            "EFI_IFR_TO_BOOLEAN",    "EFI_IFR_MID",             "EFI_IFR_FIND",          "EFI_IFR_TOKEN",
2379   "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2",          "EFI_IFR_CONDITIONAL",   "EFI_IFR_QUESTION_REF3",   "EFI_IFR_ZERO",          "EFI_IFR_ONE",
2380   "EFI_IFR_ONES",       "EFI_IFR_UNDEFINED",            "EFI_IFR_LENGTH",        "EFI_IFR_DUP",             "EFI_IFR_THIS",          "EFI_IFR_SPAN",
2381   "EFI_IFR_VALUE",      "EFI_IFR_DEFAULT",              "EFI_IFR_DEFAULTSTORE",  "EFI_IFR_FORM_MAP",        "EFI_IFR_CATENATE",      "EFI_IFR_GUID",
2382   "EFI_IFR_SECURITY",   "EFI_IFR_MODAL_TAG",            "EFI_IFR_REFRESH_ID",    "EFI_IFR_WARNING_IF",      "EFI_IFR_MATCH2",
2383 };
2384 
2385 VOID
CIFROBJ_DEBUG_PRINT(IN UINT8 OpCode)2386 CIFROBJ_DEBUG_PRINT (
2387   IN UINT8 OpCode
2388   )
2389 {
2390   printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);
2391 }
2392 #else
2393 
2394 #define CIFROBJ_DEBUG_PRINT(OpCode)
2395 
2396 #endif
2397 
2398 BOOLEAN gCreateOp = TRUE;
2399 
CIfrObj(IN UINT8 OpCode,OUT CHAR8 ** IfrObj,IN UINT8 ObjBinLen,IN BOOLEAN DelayEmit)2400 CIfrObj::CIfrObj (
2401   IN  UINT8   OpCode,
2402   OUT CHAR8   **IfrObj,
2403   IN  UINT8   ObjBinLen,
2404   IN  BOOLEAN DelayEmit
2405   )
2406 {
2407   mDelayEmit   = DelayEmit;
2408   mPkgOffset   = gCFormPkg.GetPkgLength ();
2409   mObjBinLen   = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;
2410   mObjBinBuf   = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];
2411   mRecordIdx   = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;
2412   mLineNo      = 0;
2413 
2414   assert (mObjBinBuf != NULL);
2415 
2416   if (IfrObj != NULL) {
2417     *IfrObj    = mObjBinBuf;
2418   }
2419 
2420   CIFROBJ_DEBUG_PRINT (OpCode);
2421 }
2422 
~CIfrObj(VOID)2423 CIfrObj::~CIfrObj (
2424   VOID
2425   )
2426 {
2427   if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {
2428     _EMIT_PENDING_OBJ ();
2429   }
2430 
2431   gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);
2432 }
2433 
2434 /*
2435  * The definition of CIfrObj's member function
2436  */
2437 UINT8 gScopeCount = 0;
2438 
CIfrOpHeader(IN UINT8 OpCode,IN VOID * StartAddr,IN UINT8 Length)2439 CIfrOpHeader::CIfrOpHeader (
2440   IN UINT8 OpCode,
2441   IN VOID *StartAddr,
2442   IN UINT8 Length
2443   ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr)
2444 {
2445   mHeader->OpCode = OpCode;
2446   mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;
2447   mHeader->Scope  = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;
2448 }
2449 
CIfrOpHeader(IN CIfrOpHeader & OpHdr)2450 CIfrOpHeader::CIfrOpHeader (
2451   IN CIfrOpHeader &OpHdr
2452   )
2453 {
2454   mHeader = OpHdr.mHeader;
2455 }
2456 
2457 UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };
2458