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