Fixed list file generation error which was caused by using freed buffer.
[people/mcb30/basetools.git] / 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 - 2008, 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 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   return VFR_RETURN_SUCCESS;\r
283 }\r
284 \r
285 EFI_VFR_RETURN_CODE\r
286 CFormPkg::BuildPkg (\r
287   IN FILE  *Output\r
288   )\r
289 {\r
290   EFI_VFR_RETURN_CODE     Ret;\r
291   CHAR8                   Buffer[1024];\r
292   UINT32                  Size;\r
293   EFI_HII_PACKAGE_HEADER  *PkgHdr;\r
294 \r
295   if (Output == NULL) {\r
296     return VFR_RETURN_FATAL_ERROR;\r
297   }\r
298 \r
299   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {\r
300     return Ret;\r
301   }\r
302   fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);\r
303   delete PkgHdr;\r
304 \r
305   Open ();\r
306   while ((Size = Read (Buffer, 1024)) != 0) {\r
307     fwrite (Buffer, Size, 1, Output);\r
308   }\r
309   Close ();\r
310 \r
311   return VFR_RETURN_SUCCESS;\r
312 }\r
313 \r
314 VOID\r
315 CFormPkg::_WRITE_PKG_LINE (\r
316   IN FILE   *pFile,\r
317   IN UINT32 LineBytes,\r
318   IN CHAR8  *LineHeader,\r
319   IN CHAR8  *BlkBuf,\r
320   IN UINT32 BlkSize\r
321   )\r
322 {\r
323   UINT32    Index;\r
324 \r
325   if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
326     return;\r
327   }\r
328 \r
329   for (Index = 0; Index < BlkSize; Index++) {\r
330     if ((Index % LineBytes) == 0) {\r
331       fprintf (pFile, "\n%s", LineHeader);\r
332     }\r
333     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);\r
334   }\r
335 }\r
336 \r
337 VOID\r
338 CFormPkg::_WRITE_PKG_END (\r
339   IN FILE   *pFile,\r
340   IN UINT32 LineBytes,\r
341   IN CHAR8  *LineHeader,\r
342   IN CHAR8  *BlkBuf,\r
343   IN UINT32 BlkSize\r
344   )\r
345 {\r
346   UINT32    Index;\r
347 \r
348   if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
349     return;\r
350   }\r
351 \r
352   for (Index = 0; Index < BlkSize - 1; Index++) {\r
353     if ((Index % LineBytes) == 0) {\r
354       fprintf (pFile, "\n%s", LineHeader);\r
355     }\r
356     fprintf (pFile, "0x%02X,  ", (UINT8)BlkBuf[Index]);\r
357   }\r
358 \r
359   if ((Index % LineBytes) == 0) {\r
360     fprintf (pFile, "\n%s", LineHeader);\r
361   }\r
362   fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);\r
363 }\r
364 \r
365 #define BYTES_PRE_LINE 0x10\r
366 \r
367 EFI_VFR_RETURN_CODE \r
368 CFormPkg::GenCFile (\r
369   IN CHAR8 *BaseName,\r
370   IN FILE *pFile\r
371   )\r
372 {\r
373   EFI_VFR_RETURN_CODE          Ret;\r
374   CHAR8                        Buffer[BYTES_PRE_LINE * 8];\r
375   EFI_HII_PACKAGE_HEADER       *PkgHdr;\r
376   UINT32                       PkgLength  = 0;\r
377   UINT32                       ReadSize   = 0;\r
378 \r
379   if ((BaseName == NULL) || (pFile == NULL)) {\r
380     return VFR_RETURN_FATAL_ERROR;\r
381   }\r
382 \r
383   fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);\r
384 \r
385   if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {\r
386     return Ret;\r
387   }\r
388 \r
389   fprintf (pFile, "  // ARRAY LENGTH\n");\r
390   PkgLength = PkgHdr->Length + sizeof (UINT32);\r
391   _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)&PkgLength, sizeof (UINT32));\r
392 \r
393   fprintf (pFile, "\n\n  // PACKAGE HEADER\n");\r
394   _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, "  ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
395   PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
396 \r
397   fprintf (pFile, "\n\n  // PACKAGE DATA\n");\r
398   Open ();\r
399   while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {\r
400     PkgLength += ReadSize;\r
401     if (PkgLength < PkgHdr->Length) {\r
402       _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);\r
403     } else {\r
404       _WRITE_PKG_END (pFile, BYTES_PRE_LINE, "  ", Buffer, ReadSize);\r
405     }\r
406   }\r
407   Close ();\r
408 \r
409   delete PkgHdr;\r
410   fprintf (pFile, "\n};\n");\r
411 \r
412   return VFR_RETURN_SUCCESS;\r
413 }\r
414 \r
415 EFI_VFR_RETURN_CODE\r
416 CFormPkg::AssignPending (\r
417   IN CHAR8  *Key, \r
418   IN VOID   *ValAddr, \r
419   IN UINT32 ValLen,\r
420   IN UINT32 LineNo,\r
421   IN CHAR8  *Msg\r
422   )\r
423 {\r
424   SPendingAssign *pNew;\r
425 \r
426   pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);\r
427   if (pNew == NULL) {\r
428     return VFR_RETURN_OUT_FOR_RESOURCES;\r
429   }\r
430 \r
431   pNew->mNext       = PendingAssignList;\r
432   PendingAssignList = pNew;\r
433   return VFR_RETURN_SUCCESS;\r
434 }\r
435 \r
436 VOID\r
437 CFormPkg::DoPendingAssign (\r
438   IN CHAR8  *Key, \r
439   IN VOID   *ValAddr, \r
440   IN UINT32 ValLen\r
441   )\r
442 {\r
443   SPendingAssign *pNode;\r
444 \r
445   if ((Key == NULL) || (ValAddr == NULL)) {\r
446     return;\r
447   }\r
448 \r
449   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
450     if (strcmp (pNode->mKey, Key) == 0) {\r
451       pNode->AssignValue (ValAddr, ValLen);\r
452     }\r
453   }\r
454 }\r
455 \r
456 bool\r
457 CFormPkg::HavePendingUnassigned (\r
458   VOID\r
459   )\r
460 {\r
461   SPendingAssign *pNode;\r
462 \r
463   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
464     if (pNode->mFlag == PENDING) {\r
465       return TRUE;\r
466     }\r
467   }\r
468 \r
469   return FALSE;\r
470 }\r
471 \r
472 VOID\r
473 CFormPkg::PendingAssignPrintAll (\r
474   VOID\r
475   )\r
476 {\r
477   SPendingAssign *pNode;\r
478 \r
479   for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
480     if (pNode->mFlag == PENDING) {\r
481       gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);\r
482     }\r
483   }\r
484 }\r
485 \r
486 CFormPkg gCFormPkg;\r
487 \r
488 SIfrRecord::SIfrRecord (\r
489   VOID\r
490   )\r
491 {\r
492   mIfrBinBuf = NULL;\r
493   mBinBufLen = 0;\r
494   mLineNo    = 0xFFFFFFFF;\r
495   mOffset    = 0xFFFFFFFF;\r
496   mNext      = NULL;\r
497 }\r
498 \r
499 SIfrRecord::~SIfrRecord (\r
500   VOID\r
501   )\r
502 {\r
503   if (mIfrBinBuf != NULL) {\r
504     delete mIfrBinBuf;\r
505     mIfrBinBuf = NULL;\r
506   }\r
507   mLineNo      = 0xFFFFFFFF;\r
508   mOffset      = 0xFFFFFFFF;\r
509   mBinBufLen   = 0;\r
510   mNext        = NULL;\r
511 }\r
512 \r
513 CIfrRecordInfoDB::CIfrRecordInfoDB (\r
514   VOID\r
515   )\r
516 {\r
517   mSwitch            = FALSE;\r
518   mRecordCount       = EFI_IFR_RECORDINFO_IDX_START;\r
519   mIfrRecordListHead = NULL;\r
520   mIfrRecordListTail = NULL;\r
521 }\r
522 \r
523 CIfrRecordInfoDB::~CIfrRecordInfoDB (\r
524   VOID\r
525   )\r
526 {\r
527   SIfrRecord *pNode;\r
528 \r
529   while (mIfrRecordListHead != NULL) {\r
530     pNode = mIfrRecordListHead;\r
531     mIfrRecordListHead = mIfrRecordListHead->mNext;\r
532     delete pNode;\r
533   }\r
534 }\r
535 \r
536 SIfrRecord *\r
537 CIfrRecordInfoDB::GetRecordInfoFromIdx (\r
538   IN UINT32 RecordIdx\r
539   )\r
540 {\r
541   UINT32     Idx;\r
542   SIfrRecord *pNode = NULL;\r
543 \r
544   if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {\r
545     return NULL;\r
546   }\r
547 \r
548   for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead; \r
549        (Idx != RecordIdx) && (pNode != NULL); \r
550        Idx++, pNode = pNode->mNext)\r
551   ;\r
552 \r
553   return pNode;\r
554 }\r
555 \r
556 UINT32\r
557 CIfrRecordInfoDB::IfrRecordRegister (\r
558   IN UINT32 LineNo, \r
559   IN CHAR8  *IfrBinBuf, \r
560   IN UINT8  BinBufLen,\r
561   IN UINT32 Offset\r
562   )\r
563 {\r
564   SIfrRecord *pNew;\r
565 \r
566   if (mSwitch == FALSE) {\r
567     return EFI_IFR_RECORDINFO_IDX_INVALUD;\r
568   }\r
569 \r
570   if ((pNew = new SIfrRecord) == NULL) {\r
571     return EFI_IFR_RECORDINFO_IDX_INVALUD;\r
572   }\r
573 \r
574   if (mIfrRecordListHead == NULL) {\r
575     mIfrRecordListHead = pNew;\r
576     mIfrRecordListTail = pNew;\r
577   } else {\r
578     mIfrRecordListTail->mNext = pNew;\r
579     mIfrRecordListTail = pNew;\r
580   }\r
581   mRecordCount++;\r
582 \r
583   return mRecordCount;\r
584 }\r
585 \r
586 VOID\r
587 CIfrRecordInfoDB::IfrRecordInfoUpdate (\r
588   IN UINT32 RecordIdx, \r
589   IN UINT32 LineNo,\r
590   IN CHAR8  *BinBuf,\r
591   IN UINT8  BinBufLen,\r
592   IN UINT32 Offset\r
593   )\r
594 {\r
595   SIfrRecord *pNode;\r
596 \r
597   if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {\r
598     return;\r
599   }\r
600 \r
601   pNode->mLineNo    = LineNo;\r
602   pNode->mOffset    = Offset;\r
603   pNode->mBinBufLen = BinBufLen;\r
604   if (BinBuf != NULL) {\r
605     if (pNode->mIfrBinBuf != NULL) {\r
606       delete pNode->mIfrBinBuf;\r
607     }\r
608     pNode->mIfrBinBuf = new CHAR8[BinBufLen];\r
609     if (pNode->mIfrBinBuf != NULL) {\r
610       memcpy (pNode->mIfrBinBuf, BinBuf, BinBufLen);\r
611     }\r
612   }\r
613 }\r
614 \r
615 VOID\r
616 CIfrRecordInfoDB::IfrRecordOutput (\r
617   IN FILE   *File,\r
618   IN UINT32 LineNo\r
619   )\r
620 {\r
621   SIfrRecord *pNode;\r
622   UINT8      Index;\r
623 \r
624   if (mSwitch == FALSE) {\r
625     return;\r
626   }\r
627 \r
628   if (File == NULL) {\r
629     return;\r
630   }\r
631 \r
632   for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
633     if (pNode->mLineNo == LineNo) {\r
634       fprintf (File, ">%08X: ", pNode->mOffset);\r
635       if (pNode->mIfrBinBuf != NULL) {\r
636         for (Index = 0; Index < pNode->mBinBufLen; Index++) {\r
637           fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));\r
638         }\r
639       }\r
640       fprintf (File, "\n");\r
641     }\r
642   }\r
643 }\r
644 \r
645 CIfrRecordInfoDB gCIfrRecordInfoDB;\r
646 \r
647 VOID\r
648 CIfrObj::_EMIT_PENDING_OBJ (\r
649   VOID\r
650   )\r
651 {\r
652   CHAR8  *ObjBinBuf = NULL;\r
653 \r
654   ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen);\r
655   if (ObjBinBuf != NULL) {\r
656     memcpy (ObjBinBuf, mObjBinBuf, mObjBinLen);\r
657   }\r
658 \r
659   if (mObjBinBuf != NULL) {\r
660     delete mObjBinBuf;\r
661   }\r
662 }\r
663 \r
664 /*\r
665  * The definition of CIfrObj's member function\r
666  */\r
667 static struct {\r
668   UINT8  mSize;\r
669   UINT8  mScope;\r
670 } gOpcodeSizesScopeTable[] = {\r
671   { 0, 0 },                                    // EFI_IFR_INVALID - 0x00\r
672   { sizeof (EFI_IFR_FORM), 1 },                // EFI_IFR_FORM_OP\r
673   { sizeof (EFI_IFR_SUBTITLE), 1 },            // EFI_IFR_SUBTITLE_OP\r
674   { sizeof (EFI_IFR_TEXT), 0 },                // EFI_IFR_TEXT_OP\r
675   { sizeof (EFI_IFR_IMAGE), 0 },               // EFI_IFR_IMAGE_OP\r
676   { sizeof (EFI_IFR_ONE_OF), 1 },              // EFI_IFR_ONE_OF_OP - 0x05\r
677   { sizeof (EFI_IFR_CHECKBOX), 1},             // EFI_IFR_CHECKBOX_OP\r
678   { sizeof (EFI_IFR_NUMERIC), 1 },             // EFI_IFR_NUMERIC_OP\r
679   { sizeof (EFI_IFR_PASSWORD), 1 },            // EFI_IFR_PASSWORD_OP\r
680   { sizeof (EFI_IFR_ONE_OF_OPTION), 0 },       // EFI_IFR_ONE_OF_OPTION_OP\r
681   { sizeof (EFI_IFR_SUPPRESS_IF), 1 },         // EFI_IFR_SUPPRESS_IF - 0x0A\r
682   { sizeof (EFI_IFR_LOCKED), 0 },              // EFI_IFR_LOCKED_OP\r
683   { sizeof (EFI_IFR_ACTION), 1 },              // EFI_IFR_ACTION_OP\r
684   { sizeof (EFI_IFR_RESET_BUTTON), 1 },        // EFI_IFR_RESET_BUTTON_OP\r
685   { sizeof (EFI_IFR_FORM_SET), 1 },            // EFI_IFR_FORM_SET_OP -0xE\r
686   { sizeof (EFI_IFR_REF), 0 },                 // EFI_IFR_REF_OP\r
687   { sizeof (EFI_IFR_NO_SUBMIT_IF), 1},         // EFI_IFR_NO_SUBMIT_IF_OP -0x10\r
688   { sizeof (EFI_IFR_INCONSISTENT_IF), 1 },     // EFI_IFR_INCONSISTENT_IF_OP\r
689   { sizeof (EFI_IFR_EQ_ID_VAL), 0 },           // EFI_IFR_EQ_ID_VAL_OP\r
690   { sizeof (EFI_IFR_EQ_ID_ID), 0 },            // EFI_IFR_EQ_ID_ID_OP\r
691   { sizeof (EFI_IFR_EQ_ID_LIST), 0 },          // EFI_IFR_EQ_ID_LIST_OP - 0x14\r
692   { sizeof (EFI_IFR_AND), 0 },                 // EFI_IFR_AND_OP\r
693   { sizeof (EFI_IFR_OR), 0 },                  // EFI_IFR_OR_OP\r
694   { sizeof (EFI_IFR_NOT), 0 },                 // EFI_IFR_NOT_OP\r
695   { sizeof (EFI_IFR_RULE), 1 },                // EFI_IFR_RULE_OP\r
696   { sizeof (EFI_IFR_GRAY_OUT_IF), 1 },         // EFI_IFR_GRAYOUT_IF_OP - 0x19\r
697   { sizeof (EFI_IFR_DATE), 1 },                // EFI_IFR_DATE_OP\r
698   { sizeof (EFI_IFR_TIME), 1 },                // EFI_IFR_TIME_OP\r
699   { sizeof (EFI_IFR_STRING), 1 },              // EFI_IFR_STRING_OP\r
700   { sizeof (EFI_IFR_REFRESH), 1 },             // EFI_IFR_REFRESH_OP\r
701   { sizeof (EFI_IFR_DISABLE_IF), 1 },          // EFI_IFR_DISABLE_IF_OP - 0x1E\r
702   { 0, 0 },                                    // 0x1F\r
703   { sizeof (EFI_IFR_TO_LOWER), 0 },            // EFI_IFR_TO_LOWER_OP - 0x20\r
704   { sizeof (EFI_IFR_TO_UPPER), 0 },            // EFI_IFR_TO_UPPER_OP - 0x21\r
705   { 0, 0 },                                    // 0x22\r
706   { sizeof (EFI_IFR_ORDERED_LIST), 1 },        // EFI_IFR_ORDERED_LIST_OP - 0x23\r
707   { sizeof (EFI_IFR_VARSTORE), 0 },            // EFI_IFR_VARSTORE_OP\r
708   { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP\r
709   { sizeof (EFI_IFR_VARSTORE_EFI), 0 },        // EFI_IFR_VARSTORE_EFI_OP\r
710   { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 },     // EFI_IFR_VARSTORE_DEVICE_OP\r
711   { sizeof (EFI_IFR_VERSION), 0 },             // EFI_IFR_VERSION_OP - 0x28\r
712   { sizeof (EFI_IFR_END), 0 },                 // EFI_IFR_END_OP\r
713   { sizeof (EFI_IFR_MATCH), 1 },               // EFI_IFR_MATCH_OP - 0x2A\r
714   { 0, 0 }, { 0, 0} , { 0, 0} , { 0, 0} ,      // 0x2B ~ 0x2E\r
715   { sizeof (EFI_IFR_EQUAL), 0 },               // EFI_IFR_EQUAL_OP - 0x2F\r
716   { sizeof (EFI_IFR_NOT_EQUAL), 0 },           // EFI_IFR_NOT_EQUAL_OP\r
717   { sizeof (EFI_IFR_GREATER_THAN), 0 },        // EFI_IFR_GREATER_THAN_OP\r
718   { sizeof (EFI_IFR_GREATER_EQUAL), 0 },       // EFI_IFR_GREATER_EQUAL_OP\r
719   { sizeof (EFI_IFR_LESS_THAN), 0 },           // EFI_IFR_LESS_THAN_OP\r
720   { sizeof (EFI_IFR_LESS_EQUAL), 0 },          // EFI_IFR_LESS_EQUAL_OP - 0x34\r
721   { sizeof (EFI_IFR_BITWISE_AND), 0 },         // EFI_IFR_BITWISE_AND_OP\r
722   { sizeof (EFI_IFR_BITWISE_OR), 0 },          // EFI_IFR_BITWISE_OR_OP\r
723   { sizeof (EFI_IFR_BITWISE_NOT), 0 },         // EFI_IFR_BITWISE_NOT_OP\r
724   { sizeof (EFI_IFR_SHIFT_LEFT), 0 },          // EFI_IFR_SHIFT_LEFT_OP\r
725   { sizeof (EFI_IFR_SHIFT_RIGHT), 0 },         // EFI_IFR_SHIFT_RIGHT_OP\r
726   { sizeof (EFI_IFR_ADD), 0 },                 // EFI_IFR_ADD_OP - 0x3A\r
727   { sizeof (EFI_IFR_SUBTRACT), 0 },            // EFI_IFR_SUBTRACT_OP\r
728   { sizeof (EFI_IFR_MULTIPLY), 0 },            // EFI_IFR_MULTIPLY_OP\r
729   { sizeof (EFI_IFR_DIVIDE), 0 },              // EFI_IFR_DIVIDE_OP\r
730   { sizeof (EFI_IFR_MODULO), 0 },              // EFI_IFR_MODULO_OP - 0x3E\r
731   { sizeof (EFI_IFR_RULE_REF), 0 },            // EFI_IFR_RULE_REF_OP\r
732   { sizeof (EFI_IFR_QUESTION_REF1), 0 },       // EFI_IFR_QUESTION_REF1_OP\r
733   { sizeof (EFI_IFR_QUESTION_REF2), 0 },       // EFI_IFR_QUESTION_REF2_OP - 0x41\r
734   { sizeof (EFI_IFR_UINT8), 0},                // EFI_IFR_UINT8\r
735   { sizeof (EFI_IFR_UINT16), 0},               // EFI_IFR_UINT16\r
736   { sizeof (EFI_IFR_UINT32), 0},               // EFI_IFR_UINT32\r
737   { sizeof (EFI_IFR_UINT64), 0},               // EFI_IFR_UTNT64\r
738   { sizeof (EFI_IFR_TRUE), 0 },                // EFI_IFR_TRUE_OP - 0x46\r
739   { sizeof (EFI_IFR_FALSE), 0 },               // EFI_IFR_FALSE_OP\r
740   { sizeof (EFI_IFR_TO_UINT), 0 },             // EFI_IFR_TO_UINT_OP\r
741   { sizeof (EFI_IFR_TO_STRING), 0 },           // EFI_IFR_TO_STRING_OP\r
742   { sizeof (EFI_IFR_TO_BOOLEAN), 0 },          // EFI_IFR_TO_BOOLEAN_OP\r
743   { sizeof (EFI_IFR_MID), 0 },                 // EFI_IFR_MID_OP\r
744   { sizeof (EFI_IFR_FIND), 0 },                // EFI_IFR_FIND_OP\r
745   { sizeof (EFI_IFR_TOKEN), 0 },               // EFI_IFR_TOKEN_OP\r
746   { sizeof (EFI_IFR_STRING_REF1), 0 },         // EFI_IFR_STRING_REF1_OP - 0x4E\r
747   { sizeof (EFI_IFR_STRING_REF2), 0 },         // EFI_IFR_STRING_REF2_OP\r
748   { sizeof (EFI_IFR_CONDITIONAL), 0 },         // EFI_IFR_CONDITIONAL_OP\r
749   { sizeof (EFI_IFR_QUESTION_REF3), 0 },       // EFI_IFR_QUESTION_REF3_OP\r
750   { sizeof (EFI_IFR_ZERO), 0 },                // EFI_IFR_ZERO_OP\r
751   { sizeof (EFI_IFR_ONE), 0 },                 // EFI_IFR_ONE_OP\r
752   { sizeof (EFI_IFR_ONES), 0 },                // EFI_IFR_ONES_OP\r
753   { sizeof (EFI_IFR_UNDEFINED), 0 },           // EFI_IFR_UNDEFINED_OP\r
754   { sizeof (EFI_IFR_LENGTH), 0 },              // EFI_IFR_LENGTH_OP\r
755   { sizeof (EFI_IFR_DUP), 0 },                 // EFI_IFR_DUP_OP - 0x57\r
756   { sizeof (EFI_IFR_THIS), 0 },                // EFI_IFR_THIS_OP\r
757   { sizeof (EFI_IFR_SPAN), 0 },                // EFI_IFR_SPAN_OP\r
758   { sizeof (EFI_IFR_VALUE), 1 },               // EFI_IFR_VALUE_OP\r
759   { sizeof (EFI_IFR_DEFAULT), 0 },             // EFI_IFR_DEFAULT_OP\r
760   { sizeof (EFI_IFR_DEFAULTSTORE), 0 },        // EFI_IFR_DEFAULTSTORE_OP - 0x5C\r
761   { 0, 0},                                     // 0x5D\r
762   { sizeof (EFI_IFR_CATENATE), 0 },            // EFI_IFR_CATENATE_OP\r
763   { sizeof (EFI_IFR_GUID), 0 },                // EFI_IFR_GUID_OP\r
764 };\r
765 \r
766 #ifdef CIFROBJ_DEUBG\r
767 static struct {\r
768   CHAR8 *mIfrName;\r
769 } gIfrObjPrintDebugTable[] = {\r
770   "EFI_IFR_INVALID",    "EFI_IFR_FORM",                 "EFI_IFR_SUBTITLE",      "EFI_IFR_TEXT",            "EFI_IFR_IMAGE",         "EFI_IFR_ONE_OF",\r
771   "EFI_IFR_CHECKBOX",   "EFI_IFR_NUMERIC",              "EFI_IFR_PASSWORD",      "EFI_IFR_ONE_OF_OPTION",   "EFI_IFR_SUPPRESS_IF",   "EFI_IFR_LOCKED",\r
772   "EFI_IFR_ACTION",     "EFI_IFR_RESET_BUTTON",         "EFI_IFR_FORM_SET",      "EFI_IFR_REF",             "EFI_IFR_NO_SUBMIT_IF",  "EFI_IFR_INCONSISTENT_IF",\r
773   "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
774   "EFI_IFR_RULE",       "EFI_IFR_GRAY_OUT_IF",          "EFI_IFR_DATE",          "EFI_IFR_TIME",            "EFI_IFR_STRING",        "EFI_IFR_REFRESH",\r
775   "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID",              "EFI_IFR_TO_LOWER",      "EFI_IFR_TO_UPPER",        "EFI_IFR_INVALID",       "EFI_IFR_ORDERED_LIST",\r
776   "EFI_IFR_VARSTORE",   "EFI_IFR_VARSTORE_NAME_VALUE",  "EFI_IFR_VARSTORE_EFI",  "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION",       "EFI_IFR_END",\r
777   "EFI_IFR_MATCH",      "EFI_IFR_INVALID",              "EFI_IFR_INVALID",       "EFI_IFR_INVALID",         "EFI_IFR_INVALID",       "EFI_IFR_EQUAL",\r
778   "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
779   "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT",          "EFI_IFR_SHIFT_LEFT",    "EFI_IFR_SHIFT_RIGHT",     "EFI_IFR_ADD",           "EFI_IFR_SUBTRACT",\r
780   "EFI_IFR_MULTIPLY",   "EFI_IFR_DIVIDE",               "EFI_IFR_MODULO",        "EFI_IFR_RULE_REF",        "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",\r
781   "EFI_IFR_UINT8",      "EFI_IFR_UINT16",               "EFI_IFR_UINT32",        "EFI_IFR_UINT64",          "EFI_IFR_TRUE",          "EFI_IFR_FALSE",\r
782   "EFI_IFR_TO_UINT",    "EFI_IFR_TO_STRING",            "EFI_IFR_TO_BOOLEAN",    "EFI_IFR_MID",             "EFI_IFR_FIND",          "EFI_IFR_TOKEN",\r
783   "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2",          "EFI_IFR_CONDITIONAL",   "EFI_IFR_QUESTION_REF3",   "EFI_IFR_ZERO",          "EFI_IFR_ONE",\r
784   "EFI_IFR_ONES",       "EFI_IFR_UNDEFINED",            "EFI_IFR_LENGTH",        "EFI_IFR_DUP",             "EFI_IFR_THIS",          "EFI_IFR_SPAN",\r
785   "EFI_IFR_VALUE",      "EFI_IFR_DEFAULT",              "EFI_IFR_DEFAULTSTORE",  "EFI_IFR_INVALID",         "EFI_IFR_CATENATE",      "EFI_IFR_GUID",\r
786 };\r
787 \r
788 VOID\r
789 CIFROBJ_DEBUG_PRINT (\r
790   IN UINT8 OpCode\r
791   )\r
792 {\r
793   printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);\r
794 }\r
795 #else\r
796 \r
797 #define CIFROBJ_DEBUG_PRINT(OpCode)\r
798 \r
799 #endif\r
800 \r
801 bool gCreateOp = TRUE;\r
802 \r
803 CIfrObj::CIfrObj (\r
804   IN  UINT8   OpCode,\r
805   OUT CHAR8   **IfrObj,\r
806   IN  UINT8   ObjBinLen,\r
807   IN  BOOLEAN DelayEmit\r
808   )\r
809 {\r
810   mDelayEmit   = DelayEmit;\r
811   mPkgOffset   = gCFormPkg.GetPkgLength ();\r
812   mObjBinLen   = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;\r
813   mObjBinBuf   = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];\r
814   mRecordIdx   = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;\r
815 \r
816   if (IfrObj != NULL) {\r
817     *IfrObj    = mObjBinBuf;\r
818   }\r
819 \r
820   CIFROBJ_DEBUG_PRINT (OpCode);\r
821 }\r
822 \r
823 CIfrObj::~CIfrObj (\r
824   VOID\r
825   )\r
826 {\r
827   gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);\r
828 \r
829   if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {\r
830     _EMIT_PENDING_OBJ ();\r
831   }\r
832 }\r
833 \r
834 /*\r
835  * The definition of CIfrObj's member function\r
836  */\r
837 UINT8 gScopeCount = 0;\r
838 \r
839 CIfrOpHeader::CIfrOpHeader (\r
840   IN UINT8 OpCode, \r
841   IN VOID *StartAddr,\r
842   IN UINT8 Length \r
843   ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr) \r
844 {\r
845   mHeader->OpCode = OpCode;\r
846   mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;\r
847   mHeader->Scope  = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;\r
848 }\r
849 \r
850 CIfrOpHeader::CIfrOpHeader (\r
851   IN CIfrOpHeader &OpHdr\r
852   )\r
853 {\r
854   mHeader = OpHdr.mHeader;\r
855 }\r
856 \r
857 UINT32 CIfrForm::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };\r