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