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