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