3 The definition of CFormPkg's member function
5 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "VfrFormPkg.h"
15 * The definition of CFormPkg's member function
18 SPendingAssign::SPendingAssign (
34 mKey
= new CHAR8
[strlen (Key
) + 1];
41 mMsg
= new CHAR8
[strlen (Msg
) + 1];
48 SPendingAssign::~SPendingAssign (
65 SPendingAssign::SetAddrAndLen (
75 SPendingAssign::AssignValue (
80 memmove (mAddr
, Addr
, (mLen
< Len
? mLen
: Len
));
85 SPendingAssign::GetKey (
102 mBufferNodeQueueHead
= NULL
;
103 mBufferNodeQueueTail
= NULL
;
104 mCurrBufferNode
= NULL
;
105 mReadBufferNode
= NULL
;
106 mReadBufferOffset
= 0;
107 PendingAssignList
= NULL
;
109 Node
= new SBufferNode
;
113 BufferStart
= new CHAR8
[BufferSize
];
114 if (BufferStart
== NULL
) {
118 BufferEnd
= BufferStart
+ BufferSize
;
120 memset (BufferStart
, 0, BufferSize
);
121 Node
->mBufferStart
= BufferStart
;
122 Node
->mBufferEnd
= BufferEnd
;
123 Node
->mBufferFree
= BufferStart
;
126 mBufferSize
= BufferSize
;
127 mBufferNodeQueueHead
= Node
;
128 mBufferNodeQueueTail
= Node
;
129 mCurrBufferNode
= Node
;
132 CFormPkg::~CFormPkg ()
135 SPendingAssign
*pPNode
;
137 while (mBufferNodeQueueHead
!= NULL
) {
138 pBNode
= mBufferNodeQueueHead
;
139 mBufferNodeQueueHead
= mBufferNodeQueueHead
->mNext
;
140 if (pBNode
->mBufferStart
!= NULL
) {
141 delete[] pBNode
->mBufferStart
;
145 mBufferNodeQueueTail
= NULL
;
146 mCurrBufferNode
= NULL
;
148 while (PendingAssignList
!= NULL
) {
149 pPNode
= PendingAssignList
;
150 PendingAssignList
= PendingAssignList
->mNext
;
153 PendingAssignList
= NULL
;
157 CFormPkg::CreateNewNode (
163 Node
= new SBufferNode
;
168 Node
->mBufferStart
= new CHAR8
[mBufferSize
];
169 if (Node
->mBufferStart
== NULL
) {
173 memset (Node
->mBufferStart
, 0, mBufferSize
);
174 Node
->mBufferEnd
= Node
->mBufferStart
+ mBufferSize
;
175 Node
->mBufferFree
= Node
->mBufferStart
;
183 CFormPkg::IfrBinBufferGet (
187 CHAR8
*BinBuffer
= NULL
;
188 SBufferNode
*Node
= NULL
;
190 if ((Len
== 0) || (Len
> mBufferSize
)) {
194 if ((mCurrBufferNode
->mBufferFree
+ Len
) <= mCurrBufferNode
->mBufferEnd
) {
195 BinBuffer
= mCurrBufferNode
->mBufferFree
;
196 mCurrBufferNode
->mBufferFree
+= Len
;
198 Node
= CreateNewNode ();
203 if (mBufferNodeQueueTail
== NULL
) {
204 mBufferNodeQueueHead
= mBufferNodeQueueTail
= Node
;
206 mBufferNodeQueueTail
->mNext
= Node
;
207 mBufferNodeQueueTail
= Node
;
209 mCurrBufferNode
= Node
;
214 BinBuffer
= mCurrBufferNode
->mBufferFree
;
215 mCurrBufferNode
->mBufferFree
+= Len
;
225 CFormPkg::GetPkgLength (
237 mReadBufferNode
= mBufferNodeQueueHead
;
238 mReadBufferOffset
= 0;
246 mReadBufferNode
= NULL
;
247 mReadBufferOffset
= 0;
258 if ((Size
== 0) || (Buffer
== NULL
)) {
262 if (mReadBufferNode
== NULL
) {
266 for (Index
= 0; Index
< Size
; Index
++) {
267 if ((mReadBufferNode
->mBufferStart
+ mReadBufferOffset
) < mReadBufferNode
->mBufferFree
) {
268 Buffer
[Index
] = mReadBufferNode
->mBufferStart
[mReadBufferOffset
++];
270 if ((mReadBufferNode
= mReadBufferNode
->mNext
) == NULL
) {
273 mReadBufferOffset
= 0;
283 CFormPkg::BuildPkgHdr (
284 OUT EFI_HII_PACKAGE_HEADER
**PkgHdr
287 if (PkgHdr
== NULL
) {
288 return VFR_RETURN_FATAL_ERROR
;
291 if (((*PkgHdr
) = new EFI_HII_PACKAGE_HEADER
) == NULL
) {
292 return VFR_RETURN_OUT_FOR_RESOURCES
;
295 (*PkgHdr
)->Type
= EFI_HII_PACKAGE_FORM
;
296 (*PkgHdr
)->Length
= mPkgLength
+ sizeof (EFI_HII_PACKAGE_HEADER
);
298 return VFR_RETURN_SUCCESS
;
303 OUT PACKAGE_DATA
&TBuffer
311 if (TBuffer
.Buffer
!= NULL
) {
312 delete TBuffer
.Buffer
;
315 TBuffer
.Size
= mPkgLength
;
316 TBuffer
.Buffer
= NULL
;
317 if (TBuffer
.Size
!= 0) {
318 TBuffer
.Buffer
= new CHAR8
[TBuffer
.Size
];
320 return VFR_RETURN_SUCCESS
;
323 Temp
= TBuffer
.Buffer
;
325 while ((Size
= Read (Buffer
, 1024)) != 0) {
326 memcpy (Temp
, Buffer
, Size
);
330 return VFR_RETURN_SUCCESS
;
337 IN PACKAGE_DATA
*PkgData
340 EFI_VFR_RETURN_CODE Ret
;
343 EFI_HII_PACKAGE_HEADER
*PkgHdr
;
345 if (Output
== NULL
) {
346 return VFR_RETURN_FATAL_ERROR
;
349 if ((Ret
= BuildPkgHdr(&PkgHdr
)) != VFR_RETURN_SUCCESS
) {
352 fwrite (PkgHdr
, sizeof (EFI_HII_PACKAGE_HEADER
), 1, Output
);
355 if (PkgData
== NULL
) {
357 while ((Size
= Read (Buffer
, 1024)) != 0) {
358 fwrite (Buffer
, Size
, 1, Output
);
362 fwrite (PkgData
->Buffer
, PkgData
->Size
, 1, Output
);
365 return VFR_RETURN_SUCCESS
;
369 CFormPkg::_WRITE_PKG_LINE (
372 IN CONST CHAR8
*LineHeader
,
379 if ((pFile
== NULL
) || (LineHeader
== NULL
) || (BlkBuf
== NULL
)) {
383 for (Index
= 0; Index
< BlkSize
; Index
++) {
384 if ((Index
% LineBytes
) == 0) {
385 fprintf (pFile
, "\n%s", LineHeader
);
387 fprintf (pFile
, "0x%02X, ", (UINT8
)BlkBuf
[Index
]);
392 CFormPkg::_WRITE_PKG_END (
395 IN CONST CHAR8
*LineHeader
,
402 if ((BlkSize
== 0) || (pFile
== NULL
) || (LineHeader
== NULL
) || (BlkBuf
== NULL
)) {
406 for (Index
= 0; Index
< BlkSize
- 1; Index
++) {
407 if ((Index
% LineBytes
) == 0) {
408 fprintf (pFile
, "\n%s", LineHeader
);
410 fprintf (pFile
, "0x%02X, ", (UINT8
)BlkBuf
[Index
]);
413 if ((Index
% LineBytes
) == 0) {
414 fprintf (pFile
, "\n%s", LineHeader
);
416 fprintf (pFile
, "0x%02X\n", (UINT8
)BlkBuf
[Index
]);
419 #define BYTES_PRE_LINE 0x10
420 UINT32 gAdjustOpcodeOffset
= 0;
421 BOOLEAN gNeedAdjustOpcode
= FALSE
;
422 UINT32 gAdjustOpcodeLen
= 0;
428 IN PACKAGE_DATA
*PkgData
431 EFI_VFR_RETURN_CODE Ret
;
432 CHAR8 Buffer
[BYTES_PRE_LINE
* 8];
433 EFI_HII_PACKAGE_HEADER
*PkgHdr
;
434 UINT32 PkgLength
= 0;
437 if ((BaseName
== NULL
) || (pFile
== NULL
)) {
438 return VFR_RETURN_FATAL_ERROR
;
441 fprintf (pFile
, "\nunsigned char %sBin[] = {\n", BaseName
);
443 if ((Ret
= BuildPkgHdr(&PkgHdr
)) != VFR_RETURN_SUCCESS
) {
448 // For framework vfr file, the extension framework header will be added.
450 if (VfrCompatibleMode
) {
451 fprintf (pFile
, " // FRAMEWORK PACKAGE HEADER Length\n");
452 PkgLength
= PkgHdr
->Length
+ sizeof (UINT32
) + 2;
453 _WRITE_PKG_LINE(pFile
, BYTES_PRE_LINE
, " ", (CHAR8
*)&PkgLength
, sizeof (UINT32
));
454 fprintf (pFile
, "\n\n // FRAMEWORK PACKAGE HEADER Type\n");
456 _WRITE_PKG_LINE(pFile
, BYTES_PRE_LINE
, " ", (CHAR8
*)&PkgLength
, sizeof (UINT16
));
458 fprintf (pFile
, " // ARRAY LENGTH\n");
459 PkgLength
= PkgHdr
->Length
+ sizeof (UINT32
);
460 _WRITE_PKG_LINE(pFile
, BYTES_PRE_LINE
, " ", (CHAR8
*)&PkgLength
, sizeof (UINT32
));
463 fprintf (pFile
, "\n\n // PACKAGE HEADER\n");
464 _WRITE_PKG_LINE(pFile
, BYTES_PRE_LINE
, " ", (CHAR8
*)PkgHdr
, sizeof (EFI_HII_PACKAGE_HEADER
));
465 PkgLength
= sizeof (EFI_HII_PACKAGE_HEADER
);
467 fprintf (pFile
, "\n\n // PACKAGE DATA\n");
469 if (PkgData
== NULL
) {
471 while ((ReadSize
= Read ((CHAR8
*)Buffer
, BYTES_PRE_LINE
* 8)) != 0) {
472 PkgLength
+= ReadSize
;
473 if (PkgLength
< PkgHdr
->Length
) {
474 _WRITE_PKG_LINE (pFile
, BYTES_PRE_LINE
, " ", Buffer
, ReadSize
);
476 _WRITE_PKG_END (pFile
, BYTES_PRE_LINE
, " ", Buffer
, ReadSize
);
481 if (PkgData
->Size
% BYTES_PRE_LINE
!= 0) {
482 PkgLength
= PkgData
->Size
- (PkgData
->Size
% BYTES_PRE_LINE
);
483 _WRITE_PKG_LINE (pFile
, BYTES_PRE_LINE
, " ", PkgData
->Buffer
, PkgLength
);
484 _WRITE_PKG_END (pFile
, BYTES_PRE_LINE
, " ", PkgData
->Buffer
+ PkgLength
, PkgData
->Size
% BYTES_PRE_LINE
);
486 PkgLength
= PkgData
->Size
- BYTES_PRE_LINE
;
487 _WRITE_PKG_LINE (pFile
, BYTES_PRE_LINE
, " ", PkgData
->Buffer
, PkgLength
);
488 _WRITE_PKG_END (pFile
, BYTES_PRE_LINE
, " ", PkgData
->Buffer
+ PkgLength
, BYTES_PRE_LINE
);
493 fprintf (pFile
, "\n};\n");
495 return VFR_RETURN_SUCCESS
;
499 CFormPkg::AssignPending (
507 SPendingAssign
*pNew
;
509 pNew
= new SPendingAssign (Key
, ValAddr
, ValLen
, LineNo
, Msg
);
511 return VFR_RETURN_OUT_FOR_RESOURCES
;
514 pNew
->mNext
= PendingAssignList
;
515 PendingAssignList
= pNew
;
516 return VFR_RETURN_SUCCESS
;
520 CFormPkg::DoPendingAssign (
526 SPendingAssign
*pNode
;
528 if ((Key
== NULL
) || (ValAddr
== NULL
)) {
532 for (pNode
= PendingAssignList
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
533 if (strcmp (pNode
->mKey
, Key
) == 0) {
534 pNode
->AssignValue (ValAddr
, ValLen
);
540 CFormPkg::HavePendingUnassigned (
544 SPendingAssign
*pNode
;
546 for (pNode
= PendingAssignList
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
547 if (pNode
->mFlag
== PENDING
) {
556 CFormPkg::PendingAssignPrintAll (
560 SPendingAssign
*pNode
;
562 for (pNode
= PendingAssignList
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
563 if (pNode
->mFlag
== PENDING
) {
564 gCVfrErrorHandle
.PrintMsg (pNode
->mLineNo
, pNode
->mKey
, "Error", pNode
->mMsg
);
570 CFormPkg::GetBinBufferNodeForAddr (
571 IN CHAR8
*BinBuffAddr
574 SBufferNode
*TmpNode
;
576 TmpNode
= mBufferNodeQueueHead
;
578 while (TmpNode
!= NULL
) {
579 if (TmpNode
->mBufferStart
<= BinBuffAddr
&& TmpNode
->mBufferFree
>= BinBuffAddr
) {
583 TmpNode
= TmpNode
->mNext
;
590 CFormPkg::GetNodeBefore(
591 IN SBufferNode
*CurrentNode
594 SBufferNode
*FirstNode
= mBufferNodeQueueHead
;
595 SBufferNode
*LastNode
= mBufferNodeQueueHead
;
597 while (FirstNode
!= NULL
) {
598 if (FirstNode
== CurrentNode
) {
602 LastNode
= FirstNode
;
603 FirstNode
= FirstNode
->mNext
;
606 if (FirstNode
== NULL
) {
614 CFormPkg::InsertNodeBefore(
615 IN SBufferNode
*CurrentNode
,
616 IN SBufferNode
*NewNode
619 SBufferNode
*LastNode
= GetNodeBefore (CurrentNode
);
621 if (LastNode
== NULL
) {
622 return VFR_RETURN_MISMATCHED
;
625 NewNode
->mNext
= LastNode
->mNext
;
626 LastNode
->mNext
= NewNode
;
628 return VFR_RETURN_SUCCESS
;
632 CFormPkg::GetBufAddrBaseOnOffset (
636 SBufferNode
*TmpNode
;
638 UINT32 CurrentBufLen
;
642 for (TmpNode
= mBufferNodeQueueHead
; TmpNode
!= NULL
; TmpNode
= TmpNode
->mNext
) {
643 CurrentBufLen
= TmpNode
->mBufferFree
- TmpNode
->mBufferStart
;
644 if (Offset
>= TotalBufLen
&& Offset
< TotalBufLen
+ CurrentBufLen
) {
645 return TmpNode
->mBufferStart
+ (Offset
- TotalBufLen
);
648 TotalBufLen
+= CurrentBufLen
;
655 CFormPkg::AdjustDynamicInsertOpcode (
656 IN CHAR8
*InserPositionAddr
,
657 IN CHAR8
*InsertOpcodeAddr
,
658 IN BOOLEAN CreateOpcodeAfterParsingVfr
661 SBufferNode
*InserPositionNode
;
662 SBufferNode
*InsertOpcodeNode
;
663 SBufferNode
*NewRestoreNodeBegin
;
664 SBufferNode
*NewRestoreNodeEnd
;
665 SBufferNode
*NewLastEndNode
;
666 SBufferNode
*TmpNode
;
667 UINT32 NeedRestoreCodeLen
;
669 NewRestoreNodeEnd
= NULL
;
671 InserPositionNode
= GetBinBufferNodeForAddr(InserPositionAddr
);
672 InsertOpcodeNode
= GetBinBufferNodeForAddr(InsertOpcodeAddr
);
673 assert (InserPositionNode
!= NULL
);
674 assert (InsertOpcodeNode
!= NULL
);
676 if (InserPositionNode
== InsertOpcodeNode
) {
678 // Create New Node to save the restore opcode.
680 NeedRestoreCodeLen
= InsertOpcodeAddr
- InserPositionAddr
;
681 gAdjustOpcodeLen
= NeedRestoreCodeLen
;
682 NewRestoreNodeBegin
= CreateNewNode ();
683 if (NewRestoreNodeBegin
== NULL
) {
684 return VFR_RETURN_OUT_FOR_RESOURCES
;
686 memcpy (NewRestoreNodeBegin
->mBufferFree
, InserPositionAddr
, NeedRestoreCodeLen
);
687 NewRestoreNodeBegin
->mBufferFree
+= NeedRestoreCodeLen
;
690 // Override the restore buffer data.
692 memmove (InserPositionAddr
, InsertOpcodeAddr
, InsertOpcodeNode
->mBufferFree
- InsertOpcodeAddr
);
693 InsertOpcodeNode
->mBufferFree
-= NeedRestoreCodeLen
;
694 memset (InsertOpcodeNode
->mBufferFree
, 0, NeedRestoreCodeLen
);
697 // Create New Node to save the restore opcode.
699 NeedRestoreCodeLen
= InserPositionNode
->mBufferFree
- InserPositionAddr
;
700 gAdjustOpcodeLen
= NeedRestoreCodeLen
;
701 NewRestoreNodeBegin
= CreateNewNode ();
702 if (NewRestoreNodeBegin
== NULL
) {
703 return VFR_RETURN_OUT_FOR_RESOURCES
;
705 memcpy (NewRestoreNodeBegin
->mBufferFree
, InserPositionAddr
, NeedRestoreCodeLen
);
706 NewRestoreNodeBegin
->mBufferFree
+= NeedRestoreCodeLen
;
708 // Override the restore buffer data.
710 InserPositionNode
->mBufferFree
-= NeedRestoreCodeLen
;
712 // Link the restore data to new node.
714 NewRestoreNodeBegin
->mNext
= InserPositionNode
->mNext
;
717 // Count the Adjust opcode len.
719 TmpNode
= InserPositionNode
->mNext
;
720 while (TmpNode
!= InsertOpcodeNode
) {
721 gAdjustOpcodeLen
+= TmpNode
->mBufferFree
- TmpNode
->mBufferStart
;
722 TmpNode
= TmpNode
->mNext
;
726 // Create New Node to save the last node of restore opcode.
728 NeedRestoreCodeLen
= InsertOpcodeAddr
- InsertOpcodeNode
->mBufferStart
;
729 gAdjustOpcodeLen
+= NeedRestoreCodeLen
;
730 if (NeedRestoreCodeLen
> 0) {
731 NewRestoreNodeEnd
= CreateNewNode ();
732 if (NewRestoreNodeEnd
== NULL
) {
733 return VFR_RETURN_OUT_FOR_RESOURCES
;
735 memcpy (NewRestoreNodeEnd
->mBufferFree
, InsertOpcodeNode
->mBufferStart
, NeedRestoreCodeLen
);
736 NewRestoreNodeEnd
->mBufferFree
+= NeedRestoreCodeLen
;
738 // Override the restore buffer data.
740 memmove (InsertOpcodeNode
->mBufferStart
, InsertOpcodeAddr
, InsertOpcodeNode
->mBufferFree
- InsertOpcodeAddr
);
741 InsertOpcodeNode
->mBufferFree
-= InsertOpcodeAddr
- InsertOpcodeNode
->mBufferStart
;
744 // Insert the last restore data node.
746 TmpNode
= GetNodeBefore (InsertOpcodeNode
);
747 assert (TmpNode
!= NULL
);
749 if (TmpNode
== InserPositionNode
) {
750 NewRestoreNodeBegin
->mNext
= NewRestoreNodeEnd
;
752 TmpNode
->mNext
= NewRestoreNodeEnd
;
755 // Connect the dynamic opcode node to the node after InserPositionNode.
757 InserPositionNode
->mNext
= InsertOpcodeNode
;
761 if (CreateOpcodeAfterParsingVfr
) {
763 // Th new opcodes were created after Parsing Vfr file,
764 // so the content in mBufferNodeQueueTail must be the new created opcodes.
765 // So connet the NewRestoreNodeBegin to the tail and update the tail node.
767 mBufferNodeQueueTail
->mNext
= NewRestoreNodeBegin
;
768 if (NewRestoreNodeEnd
!= NULL
) {
769 mBufferNodeQueueTail
= NewRestoreNodeEnd
;
771 mBufferNodeQueueTail
= NewRestoreNodeBegin
;
774 if (mBufferNodeQueueTail
->mBufferFree
- mBufferNodeQueueTail
->mBufferStart
> 2) {
776 // End form set opcode all in the mBufferNodeQueueTail node.
778 NewLastEndNode
= CreateNewNode ();
779 if (NewLastEndNode
== NULL
) {
780 return VFR_RETURN_OUT_FOR_RESOURCES
;
782 NewLastEndNode
->mBufferStart
[0] = 0x29;
783 NewLastEndNode
->mBufferStart
[1] = 0x02;
784 NewLastEndNode
->mBufferFree
+= 2;
786 mBufferNodeQueueTail
->mBufferFree
-= 2;
788 mBufferNodeQueueTail
->mNext
= NewRestoreNodeBegin
;
789 if (NewRestoreNodeEnd
!= NULL
) {
790 NewRestoreNodeEnd
->mNext
= NewLastEndNode
;
792 NewRestoreNodeBegin
->mNext
= NewLastEndNode
;
795 mBufferNodeQueueTail
= NewLastEndNode
;
796 } else if (mBufferNodeQueueTail
->mBufferFree
- mBufferNodeQueueTail
->mBufferStart
== 2) {
797 TmpNode
= GetNodeBefore(mBufferNodeQueueTail
);
798 assert (TmpNode
!= NULL
);
800 TmpNode
->mNext
= NewRestoreNodeBegin
;
801 if (NewRestoreNodeEnd
!= NULL
) {
802 NewRestoreNodeEnd
->mNext
= mBufferNodeQueueTail
;
804 NewRestoreNodeBegin
->mNext
= mBufferNodeQueueTail
;
808 mCurrBufferNode
= mBufferNodeQueueTail
;
809 return VFR_RETURN_SUCCESS
;
813 CFormPkg::DeclarePendingQuestion (
814 IN CVfrVarDataTypeDB
&lCVfrVarDataTypeDB
,
815 IN CVfrDataStorage
&lCVfrDataStorage
,
816 IN CVfrQuestionDB
&lCVfrQuestionDB
,
817 IN EFI_GUID
*LocalFormSetGuid
,
819 OUT CHAR8
**InsertOpcodeAddr
822 SPendingAssign
*pNode
;
825 CHAR8 FName
[MAX_NAME_LEN
];
828 UINT32 ShrinkSize
= 0;
829 EFI_VFR_RETURN_CODE ReturnCode
;
830 EFI_VFR_VARSTORE_TYPE VarStoreType
= EFI_VFR_VARSTORE_INVALID
;
833 CIfrGuid
*GuidObj
= NULL
;
836 // Declare all questions as Numeric in DisableIf True
840 DIObj
.SetLineNo (LineNo
);
841 *InsertOpcodeAddr
= DIObj
.GetObjBinAddr
<CHAR8
>();
844 CIfrTrue
TObj (LineNo
);
846 // Declare Numeric qeustion for each undefined question.
847 for (pNode
= PendingAssignList
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
848 if (pNode
->mFlag
== PENDING
) {
849 EFI_VARSTORE_INFO Info
;
850 EFI_QUESTION_ID QId
= EFI_QUESTION_ID_INVALID
;
852 // Register this question, assume it is normal question, not date or time question
854 VarStr
= pNode
->mKey
;
855 ReturnCode
= lCVfrQuestionDB
.RegisterQuestion (NULL
, VarStr
, QId
);
856 if (ReturnCode
!= VFR_RETURN_SUCCESS
) {
857 gCVfrErrorHandle
.HandleError (ReturnCode
, pNode
->mLineNo
, pNode
->mKey
);
862 printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr
, QId
);
865 // Get Question Info, framework vfr VarName == StructName
867 ReturnCode
= lCVfrVarDataTypeDB
.ExtractFieldNameAndArrary (VarStr
, FName
, ArrayIdx
);
868 if (ReturnCode
!= VFR_RETURN_SUCCESS
) {
869 gCVfrErrorHandle
.PrintMsg (pNode
->mLineNo
, pNode
->mKey
, "Error", "Var string is not the valid C variable");
875 ReturnCode
= lCVfrDataStorage
.GetVarStoreId (FName
, &Info
.mVarStoreId
);
876 if (ReturnCode
!= VFR_RETURN_SUCCESS
) {
877 gCVfrErrorHandle
.PrintMsg (pNode
->mLineNo
, FName
, "Error", "Var Store Type is not defined");
880 VarStoreType
= lCVfrDataStorage
.GetVarStoreType (Info
.mVarStoreId
);
882 if (*VarStr
== '\0' && ArrayIdx
!= INVALID_ARRAY_INDEX
) {
883 ReturnCode
= lCVfrDataStorage
.GetNameVarStoreInfo (&Info
, ArrayIdx
);
885 if (VarStoreType
== EFI_VFR_VARSTORE_EFI
) {
886 ReturnCode
= lCVfrDataStorage
.GetEfiVarStoreInfo (&Info
);
887 } else if (VarStoreType
== EFI_VFR_VARSTORE_BUFFER
|| VarStoreType
== EFI_VFR_VARSTORE_BUFFER_BITS
) {
888 VarStr
= pNode
->mKey
;
889 //convert VarStr with store name to VarStr with structure name
890 ReturnCode
= lCVfrDataStorage
.GetBufferVarStoreDataTypeName (Info
.mVarStoreId
, &SName
);
891 if (ReturnCode
== VFR_RETURN_SUCCESS
) {
892 NewStr
= new CHAR8
[strlen (VarStr
) + strlen (SName
) + 1];
894 strcpy (NewStr
, SName
);
895 strcat (NewStr
, VarStr
+ strlen (FName
));
896 ReturnCode
= lCVfrVarDataTypeDB
.GetDataFieldInfo (NewStr
, Info
.mInfo
.mVarOffset
, Info
.mVarType
, Info
.mVarTotalSize
, Info
.mIsBitVar
);
900 ReturnCode
= VFR_RETURN_UNSUPPORTED
;
903 if (ReturnCode
!= VFR_RETURN_SUCCESS
) {
904 gCVfrErrorHandle
.HandleError (ReturnCode
, pNode
->mLineNo
, pNode
->mKey
);
908 // If the storage is bit fields, create Guid opcode to wrap the numeric opcode.
910 if (Info
.mIsBitVar
) {
911 GuidObj
= new CIfrGuid(0);
912 GuidObj
->SetGuid (&gEdkiiIfrBitVarGuid
);
913 GuidObj
->SetLineNo(LineNo
);
917 CNObj
.SetLineNo (LineNo
);
918 CNObj
.SetPrompt (0x0);
920 CNObj
.SetQuestionId (QId
);
921 CNObj
.SetVarStoreInfo (&Info
);
924 // 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.
926 if (Info
.mIsBitVar
) {
927 MaxValue
= (1 << Info
.mVarTotalSize
) -1;
928 CNObj
.SetMinMaxStepData ((UINT32
) 0, MaxValue
, (UINT32
) 0);
930 LFlags
= (EDKII_IFR_NUMERIC_SIZE_BIT
& Info
.mVarTotalSize
);
931 CNObj
.SetFlagsForBitField (0, LFlags
);
934 // Numeric doesn't support BOOLEAN data type.
935 // BOOLEAN type has the same data size to UINT8.
937 if (Info
.mVarType
== EFI_IFR_TYPE_BOOLEAN
) {
938 Info
.mVarType
= EFI_IFR_TYPE_NUM_SIZE_8
;
940 CNObj
.SetFlags (0, Info
.mVarType
);
942 // Use maximum value not to limit the valid value for the undefined question.
944 switch (Info
.mVarType
) {
945 case EFI_IFR_TYPE_NUM_SIZE_64
:
946 CNObj
.SetMinMaxStepData ((UINT64
) 0, (UINT64
) -1 , (UINT64
) 0);
949 case EFI_IFR_TYPE_NUM_SIZE_32
:
950 CNObj
.SetMinMaxStepData ((UINT32
) 0, (UINT32
) -1 , (UINT32
) 0);
953 case EFI_IFR_TYPE_NUM_SIZE_16
:
954 CNObj
.SetMinMaxStepData ((UINT16
) 0, (UINT16
) -1 , (UINT16
) 0);
957 case EFI_IFR_TYPE_NUM_SIZE_8
:
958 CNObj
.SetMinMaxStepData ((UINT8
) 0, (UINT8
) -1 , (UINT8
) 0);
965 CNObj
.ShrinkBinSize (ShrinkSize
);
968 // For undefined Efi VarStore type question
969 // Append the extended guided opcode to contain VarName
971 if (VarStoreType
== EFI_VFR_VARSTORE_EFI
|| VfrCompatibleMode
) {
972 CIfrVarEqName
CVNObj (QId
, Info
.mInfo
.mVarName
);
973 CVNObj
.SetLineNo (LineNo
);
980 CEObj
.SetLineNo (LineNo
);
982 // End for Guided opcode
984 if (GuidObj
!= NULL
) {
986 CEObjGuid
.SetLineNo (LineNo
);
987 GuidObj
->SetScope(1);
998 SEObj
.SetLineNo (LineNo
);
1000 return VFR_RETURN_SUCCESS
;
1005 SIfrRecord::SIfrRecord (
1011 mLineNo
= 0xFFFFFFFF;
1012 mOffset
= 0xFFFFFFFF;
1016 SIfrRecord::~SIfrRecord (
1020 if (mIfrBinBuf
!= NULL
) {
1021 //delete mIfrBinBuf;
1024 mLineNo
= 0xFFFFFFFF;
1025 mOffset
= 0xFFFFFFFF;
1030 CIfrRecordInfoDB::CIfrRecordInfoDB (
1035 mRecordCount
= EFI_IFR_RECORDINFO_IDX_START
;
1036 mIfrRecordListHead
= NULL
;
1037 mIfrRecordListTail
= NULL
;
1038 mAllDefaultTypeCount
= 0;
1039 for (UINT8 i
= 0; i
< EFI_HII_MAX_SUPPORT_DEFAULT_TYPE
; i
++) {
1040 mAllDefaultIdArray
[i
] = 0xffff;
1044 CIfrRecordInfoDB::~CIfrRecordInfoDB (
1050 while (mIfrRecordListHead
!= NULL
) {
1051 pNode
= mIfrRecordListHead
;
1052 mIfrRecordListHead
= mIfrRecordListHead
->mNext
;
1058 CIfrRecordInfoDB::GetRecordInfoFromIdx (
1063 SIfrRecord
*pNode
= NULL
;
1065 if (RecordIdx
== EFI_IFR_RECORDINFO_IDX_INVALUD
) {
1069 for (Idx
= (EFI_IFR_RECORDINFO_IDX_START
+ 1), pNode
= mIfrRecordListHead
;
1070 (Idx
!= RecordIdx
) && (pNode
!= NULL
);
1071 Idx
++, pNode
= pNode
->mNext
)
1078 CIfrRecordInfoDB::IfrRecordRegister (
1080 IN CHAR8
*IfrBinBuf
,
1087 if (mSwitch
== FALSE
) {
1088 return EFI_IFR_RECORDINFO_IDX_INVALUD
;
1091 if ((pNew
= new SIfrRecord
) == NULL
) {
1092 return EFI_IFR_RECORDINFO_IDX_INVALUD
;
1095 if (mIfrRecordListHead
== NULL
) {
1096 mIfrRecordListHead
= pNew
;
1097 mIfrRecordListTail
= pNew
;
1099 mIfrRecordListTail
->mNext
= pNew
;
1100 mIfrRecordListTail
= pNew
;
1104 return mRecordCount
;
1108 CIfrRecordInfoDB::IfrRecordInfoUpdate (
1109 IN UINT32 RecordIdx
,
1119 if ((pNode
= GetRecordInfoFromIdx (RecordIdx
)) == NULL
) {
1125 // Line number is not specified explicitly, try to use line number of previous opcode
1127 Prev
= GetRecordInfoFromIdx (RecordIdx
- 1);
1129 LineNo
= Prev
->mLineNo
;
1133 pNode
->mLineNo
= LineNo
;
1134 pNode
->mOffset
= Offset
;
1135 pNode
->mBinBufLen
= BinBufLen
;
1136 pNode
->mIfrBinBuf
= BinBuf
;
1141 CIfrRecordInfoDB::IfrRecordOutput (
1142 OUT PACKAGE_DATA
&TBuffer
1148 if (TBuffer
.Buffer
!= NULL
) {
1149 delete[] TBuffer
.Buffer
;
1153 TBuffer
.Buffer
= NULL
;
1156 if (mSwitch
== FALSE
) {
1160 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1161 TBuffer
.Size
+= pNode
->mBinBufLen
;
1164 if (TBuffer
.Size
!= 0) {
1165 TBuffer
.Buffer
= new CHAR8
[TBuffer
.Size
];
1170 Temp
= TBuffer
.Buffer
;
1172 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1173 if (pNode
->mIfrBinBuf
!= NULL
) {
1174 memcpy (Temp
, pNode
->mIfrBinBuf
, pNode
->mBinBufLen
);
1175 Temp
+= pNode
->mBinBufLen
;
1183 CIfrRecordInfoDB::IfrRecordOutput (
1192 if (mSwitch
== FALSE
) {
1202 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1203 if (pNode
->mLineNo
== LineNo
|| LineNo
== 0) {
1204 fprintf (File
, ">%08X: ", pNode
->mOffset
);
1205 TotalSize
+= pNode
->mBinBufLen
;
1206 if (pNode
->mIfrBinBuf
!= NULL
) {
1207 for (Index
= 0; Index
< pNode
->mBinBufLen
; Index
++) {
1208 fprintf (File
, "%02X ", (UINT8
)(pNode
->mIfrBinBuf
[Index
]));
1211 fprintf (File
, "\n");
1216 fprintf (File
, "\nTotal Size of all record is 0x%08X\n", TotalSize
);
1221 // for framework vfr file
1222 // adjust opcode sequence for uefi IFR format
1223 // adjust inconsistent and varstore into the right position.
1226 CIfrRecordInfoDB::CheckQuestionOpCode (
1231 case EFI_IFR_CHECKBOX_OP
:
1232 case EFI_IFR_NUMERIC_OP
:
1233 case EFI_IFR_PASSWORD_OP
:
1234 case EFI_IFR_ONE_OF_OP
:
1235 case EFI_IFR_ACTION_OP
:
1236 case EFI_IFR_STRING_OP
:
1237 case EFI_IFR_DATE_OP
:
1238 case EFI_IFR_TIME_OP
:
1239 case EFI_IFR_ORDERED_LIST_OP
:
1240 case EFI_IFR_REF_OP
:
1248 CIfrRecordInfoDB::CheckIdOpCode (
1253 case EFI_IFR_EQ_ID_VAL_OP
:
1254 case EFI_IFR_EQ_ID_ID_OP
:
1255 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
1256 case EFI_IFR_QUESTION_REF1_OP
:
1264 CIfrRecordInfoDB::GetOpcodeQuestionId (
1265 IN EFI_IFR_OP_HEADER
*OpHead
1268 EFI_IFR_QUESTION_HEADER
*QuestionHead
;
1270 QuestionHead
= (EFI_IFR_QUESTION_HEADER
*) (OpHead
+ 1);
1272 return QuestionHead
->QuestionId
;
1276 CIfrRecordInfoDB::GetRecordInfoFromOffset (
1280 SIfrRecord
*pNode
= NULL
;
1282 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1283 if (pNode
->mOffset
== Offset
) {
1292 Add just the op code position.
1294 Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,
1295 so pDynamicOpcodeNodes is before mIfrRecordListTail.
1299 |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|
1303 |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|
1305 Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,
1306 so new records are appennded to the end of OriginalIfrRecordListTail.
1310 |mIfrRecordListHead + ...+ pAdjustNode + ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|
1314 |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + ... + OriginalIfrRecordListTail|
1317 @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.
1321 CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (
1322 IN BOOLEAN CreateOpcodeAfterParsingVfr
1325 UINT32 OpcodeOffset
;
1326 SIfrRecord
*pNode
, *pPreNode
;
1327 SIfrRecord
*pAdjustNode
, *pNodeBeforeAdjust
;
1328 SIfrRecord
*pNodeBeforeDynamic
;
1332 pNodeBeforeDynamic
= NULL
;
1336 // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,
1337 // and the node before pDynamicOpcodeNode.
1339 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1340 if (OpcodeOffset
== gAdjustOpcodeOffset
) {
1341 pAdjustNode
= pNode
;
1342 pNodeBeforeAdjust
= pPreNode
;
1343 } else if (OpcodeOffset
== gAdjustOpcodeOffset
+ gAdjustOpcodeLen
) {
1344 pNodeBeforeDynamic
= pPreNode
;
1346 if (pNode
->mNext
!= NULL
) {
1349 OpcodeOffset
+= pNode
->mBinBufLen
;
1353 // Check the nodes whether exist.
1355 if (pNodeBeforeDynamic
== NULL
|| pAdjustNode
== NULL
|| pNodeBeforeAdjust
== NULL
) {
1360 // Adjust the node. pPreNode save the Node before mIfrRecordListTail
1362 pNodeBeforeAdjust
->mNext
= pNodeBeforeDynamic
->mNext
;
1363 if (CreateOpcodeAfterParsingVfr
) {
1365 // mIfrRecordListTail is the end of pDynamicNode (Case2).
1367 mIfrRecordListTail
->mNext
= pAdjustNode
;
1368 mIfrRecordListTail
= pNodeBeforeDynamic
;
1369 mIfrRecordListTail
->mNext
= NULL
;
1372 //pPreNode is the end of pDynamicNode(Case1).
1374 pPreNode
->mNext
= pAdjustNode
;
1375 pNodeBeforeDynamic
->mNext
= mIfrRecordListTail
;
1382 Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.
1384 @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.
1388 CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (
1389 IN BOOLEAN CreateOpcodeAfterParsingVfr
1392 SIfrRecord
*pRecord
;
1395 // Base on the original offset info to update the record list.
1397 if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr
)) {
1398 gCVfrErrorHandle
.PrintMsg (0, (CHAR8
*)"Error", (CHAR8
*)"Can not find the adjust offset in the record.");
1402 // Base on the opcode binary length to recalculate the offset for each opcode.
1404 IfrAdjustOffsetForRecord();
1407 // Base on the offset to find the binary address.
1409 pRecord
= GetRecordInfoFromOffset(gAdjustOpcodeOffset
);
1410 while (pRecord
!= NULL
) {
1411 pRecord
->mIfrBinBuf
= gCFormPkg
.GetBufAddrBaseOnOffset(pRecord
->mOffset
);
1412 pRecord
= pRecord
->mNext
;
1418 CIfrRecordInfoDB::IfrAdjustOffsetForRecord (
1422 UINT32 OpcodeOffset
;
1426 for (pNode
= mIfrRecordListHead
; pNode
!= NULL
; pNode
= pNode
->mNext
) {
1427 pNode
->mOffset
= OpcodeOffset
;
1428 OpcodeOffset
+= pNode
->mBinBufLen
;
1433 CIfrRecordInfoDB::IfrRecordAdjust (
1437 SIfrRecord
*pNode
, *preNode
;
1438 SIfrRecord
*uNode
, *tNode
;
1439 EFI_IFR_OP_HEADER
*OpHead
, *tOpHead
;
1440 EFI_QUESTION_ID QuestionId
;
1442 UINT32 QuestionScope
;
1443 CHAR8 ErrorMsg
[MAX_STRING_LEN
] = {0, };
1444 EFI_VFR_RETURN_CODE Status
;
1447 // Init local variable
1449 Status
= VFR_RETURN_SUCCESS
;
1450 pNode
= mIfrRecordListHead
;
1453 while (pNode
!= NULL
) {
1454 OpHead
= (EFI_IFR_OP_HEADER
*) pNode
->mIfrBinBuf
;
1457 // make sure the inconsistent opcode in question scope
1459 if (QuestionScope
> 0) {
1460 QuestionScope
+= OpHead
->Scope
;
1461 if (OpHead
->OpCode
== EFI_IFR_END_OP
) {
1466 if (CheckQuestionOpCode (OpHead
->OpCode
)) {
1470 // for the inconsistent opcode not in question scope, adjust it
1472 if (OpHead
->OpCode
== EFI_IFR_INCONSISTENT_IF_OP
&& QuestionScope
== 0) {
1474 // for inconsistent opcode not in question scope
1478 // Count inconsistent opcode Scope
1480 StackCount
= OpHead
->Scope
;
1481 QuestionId
= EFI_QUESTION_ID_INVALID
;
1483 while (tNode
!= NULL
&& StackCount
> 0) {
1484 tNode
= tNode
->mNext
;
1485 tOpHead
= (EFI_IFR_OP_HEADER
*) tNode
->mIfrBinBuf
;
1487 // Calculate Scope Number
1489 StackCount
+= tOpHead
->Scope
;
1490 if (tOpHead
->OpCode
== EFI_IFR_END_OP
) {
1494 // by IdEqual opcode to get QuestionId
1496 if (QuestionId
== EFI_QUESTION_ID_INVALID
&&
1497 CheckIdOpCode (tOpHead
->OpCode
)) {
1498 QuestionId
= *(EFI_QUESTION_ID
*) (tOpHead
+ 1);
1501 if (tNode
== NULL
|| QuestionId
== EFI_QUESTION_ID_INVALID
) {
1503 // report error; not found
1505 sprintf (ErrorMsg
, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId
);
1506 gCVfrErrorHandle
.PrintMsg (0, NULL
, "Error", ErrorMsg
);
1507 Status
= VFR_RETURN_MISMATCHED
;
1511 // extract inconsistent opcode list
1512 // pNode is Inconsistent opcode, tNode is End Opcode
1516 // insert inconsistent opcode list into the right question scope by questionid
1518 for (uNode
= mIfrRecordListHead
; uNode
!= NULL
; uNode
= uNode
->mNext
) {
1519 tOpHead
= (EFI_IFR_OP_HEADER
*) uNode
->mIfrBinBuf
;
1520 if (CheckQuestionOpCode (tOpHead
->OpCode
) &&
1521 (QuestionId
== GetOpcodeQuestionId (tOpHead
))) {
1526 // insert inconsistent opcode list and check LATE_CHECK flag
1528 if (uNode
!= NULL
) {
1529 if ((((EFI_IFR_QUESTION_HEADER
*)(tOpHead
+ 1))->Flags
& 0x20) != 0) {
1531 // if LATE_CHECK flag is set, change inconsistent to nosumbit
1533 OpHead
->OpCode
= EFI_IFR_NO_SUBMIT_IF_OP
;
1537 // skip the default storage for Date and Time
1539 if ((uNode
->mNext
!= NULL
) && (*uNode
->mNext
->mIfrBinBuf
== EFI_IFR_DEFAULT_OP
)) {
1540 uNode
= uNode
->mNext
;
1543 preNode
->mNext
= tNode
->mNext
;
1544 tNode
->mNext
= uNode
->mNext
;
1545 uNode
->mNext
= pNode
;
1547 // reset pNode to head list, scan the whole list again.
1549 pNode
= mIfrRecordListHead
;
1555 // not found matched question id, report error
1557 sprintf (ErrorMsg
, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId
);
1558 gCVfrErrorHandle
.PrintMsg (0, NULL
, "Error", ErrorMsg
);
1559 Status
= VFR_RETURN_MISMATCHED
;
1562 } else if (OpHead
->OpCode
== EFI_IFR_VARSTORE_OP
||
1563 OpHead
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1565 // for new added group of varstore opcode
1568 while (tNode
->mNext
!= NULL
) {
1569 tOpHead
= (EFI_IFR_OP_HEADER
*) tNode
->mNext
->mIfrBinBuf
;
1570 if (tOpHead
->OpCode
!= EFI_IFR_VARSTORE_OP
&&
1571 tOpHead
->OpCode
!= EFI_IFR_VARSTORE_EFI_OP
) {
1574 tNode
= tNode
->mNext
;
1577 if (tNode
->mNext
== NULL
) {
1579 // invalid IfrCode, IfrCode end by EndOpCode
1581 gCVfrErrorHandle
.PrintMsg (0, NULL
, "Error", "No found End Opcode in the end");
1582 Status
= VFR_RETURN_MISMATCHED
;
1586 if (tOpHead
->OpCode
!= EFI_IFR_END_OP
) {
1588 // not new added varstore, which are not needed to be adjust.
1591 pNode
= tNode
->mNext
;
1595 // move new added varstore opcode to the position befor form opcode
1596 // varstore opcode between pNode and tNode
1600 // search form opcode from begin
1602 for (uNode
= mIfrRecordListHead
; uNode
->mNext
!= NULL
; uNode
= uNode
->mNext
) {
1603 tOpHead
= (EFI_IFR_OP_HEADER
*) uNode
->mNext
->mIfrBinBuf
;
1604 if (tOpHead
->OpCode
== EFI_IFR_FORM_OP
) {
1609 // Insert varstore opcode beform form opcode if form opcode is found
1611 if (uNode
->mNext
!= NULL
) {
1612 preNode
->mNext
= tNode
->mNext
;
1613 tNode
->mNext
= uNode
->mNext
;
1614 uNode
->mNext
= pNode
;
1616 // reset pNode to head list, scan the whole list again.
1618 pNode
= mIfrRecordListHead
;
1624 // not found form, continue scan IfrRecord list
1627 pNode
= tNode
->mNext
;
1636 pNode
= pNode
->mNext
;
1640 // Update Ifr Opcode Offset
1642 if (Status
== VFR_RETURN_SUCCESS
) {
1643 IfrAdjustOffsetForRecord ();
1649 When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not
1650 given by expression, should save the default info for the Buffer VarStore.
1652 @param DefaultId The default id.
1653 @param pQuestionNode Point to the question opcode node.
1654 @param Value The default value.
1657 CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (
1658 IN UINT16 DefaultId
,
1659 IN SIfrRecord
*pQuestionNode
,
1660 IN EFI_IFR_TYPE_VALUE Value
1663 CHAR8
*VarStoreName
= NULL
;
1664 EFI_VFR_VARSTORE_TYPE VarStoreType
= EFI_VFR_VARSTORE_INVALID
;
1665 EFI_GUID
*VarGuid
= NULL
;
1666 EFI_VARSTORE_INFO VarInfo
;
1667 EFI_IFR_QUESTION_HEADER
*QuestionHead
;
1668 EFI_IFR_OP_HEADER
*pQuestionOpHead
;
1670 pQuestionOpHead
= (EFI_IFR_OP_HEADER
*) pQuestionNode
->mIfrBinBuf
;
1671 QuestionHead
= (EFI_IFR_QUESTION_HEADER
*) (pQuestionOpHead
+ 1);
1674 // Get the Var Store name and type.
1676 gCVfrDataStorage
.GetVarStoreName (QuestionHead
->VarStoreId
, &VarStoreName
);
1677 VarGuid
= gCVfrDataStorage
.GetVarStoreGuid (QuestionHead
->VarStoreId
);
1678 VarStoreType
= gCVfrDataStorage
.GetVarStoreType (QuestionHead
->VarStoreId
);
1681 // Only for Buffer storage need to save the default info in the storage.
1682 // Other type storage, just return.
1684 if (VarStoreType
!= EFI_VFR_VARSTORE_BUFFER
) {
1687 VarInfo
.mInfo
.mVarOffset
= QuestionHead
->VarStoreInfo
.VarOffset
;
1688 VarInfo
.mVarStoreId
= QuestionHead
->VarStoreId
;
1692 // Get the buffer storage info about this question.
1694 gCVfrDataStorage
.GetBufferVarStoreFieldInfo (&VarInfo
);
1699 gCVfrDefaultStore
.BufferVarStoreAltConfigAdd (
1710 Record the number and default id of all defaultstore opcode.
1714 CIfrRecordInfoDB::IfrGetDefaultStoreInfo (
1719 EFI_IFR_OP_HEADER
*pOpHead
;
1720 EFI_IFR_DEFAULTSTORE
*DefaultStore
;
1722 pNode
= mIfrRecordListHead
;
1723 mAllDefaultTypeCount
= 0;
1725 while (pNode
!= NULL
) {
1726 pOpHead
= (EFI_IFR_OP_HEADER
*) pNode
->mIfrBinBuf
;
1728 if (pOpHead
->OpCode
== EFI_IFR_DEFAULTSTORE_OP
){
1729 DefaultStore
= (EFI_IFR_DEFAULTSTORE
*) pNode
->mIfrBinBuf
;
1730 mAllDefaultIdArray
[mAllDefaultTypeCount
++] = DefaultStore
->DefaultId
;
1732 pNode
= pNode
->mNext
;
1737 Create new default opcode record.
1739 @param Size The new default opcode size.
1740 @param DefaultId The new default id.
1741 @param Type The new default type.
1742 @param LineNo The line number of the new record.
1743 @param Value The new default value.
1747 CIfrRecordInfoDB::IfrCreateDefaultRecord(
1749 IN UINT16 DefaultId
,
1752 IN EFI_IFR_TYPE_VALUE Value
1756 CIfrDefault2
*DObj2
;
1761 if (Type
== EFI_IFR_TYPE_OTHER
) {
1762 DObj2
= new CIfrDefault2 (Size
);
1763 DObj2
->SetDefaultId(DefaultId
);
1764 DObj2
->SetType(Type
);
1765 DObj2
->SetLineNo(LineNo
);
1766 DObj2
->SetScope (1);
1769 DObj
= new CIfrDefault (Size
);
1770 DObj
->SetDefaultId(DefaultId
);
1771 DObj
->SetType(Type
);
1772 DObj
->SetLineNo(LineNo
);
1773 DObj
->SetValue (Value
);
1779 Create new default opcode for question base on the QuestionDefaultInfo.
1781 @param pQuestionNode Point to the question opcode Node.
1782 @param QuestionDefaultInfo Point to the QuestionDefaultInfo for current question.
1786 CIfrRecordInfoDB::IfrCreateDefaultForQuestion (
1787 IN SIfrRecord
*pQuestionNode
,
1788 IN QuestionDefaultRecord
*QuestionDefaultInfo
1791 EFI_IFR_OP_HEADER
*pOpHead
;
1792 EFI_IFR_DEFAULT
*Default
;
1795 SIfrRecord
*pDefaultNode
;
1802 EFI_IFR_ONE_OF_OPTION
*DefaultOptionOpcode
;
1803 EFI_IFR_TYPE_VALUE CheckBoxDefaultValue
;
1805 CheckBoxDefaultValue
.b
= 1;
1806 pOpHead
= (EFI_IFR_OP_HEADER
*) pQuestionNode
->mIfrBinBuf
;
1812 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1814 gAdjustOpcodeOffset
= pQuestionNode
->mNext
->mOffset
;
1817 // For oneof, the default with smallest default id is given by the option flag.
1818 // So create the missing defaults base on the oneof option value(mDefaultValueRecord).
1820 if (pOpHead
->OpCode
== EFI_IFR_ONE_OF_OP
&& !QuestionDefaultInfo
->mIsDefaultOpcode
) {
1821 DefaultOptionOpcode
= (EFI_IFR_ONE_OF_OPTION
*)QuestionDefaultInfo
->mDefaultValueRecord
->mIfrBinBuf
;
1822 DefaultSize
= QuestionDefaultInfo
->mDefaultValueRecord
->mBinBufLen
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
);
1823 DefaultSize
+= OFFSET_OF (EFI_IFR_DEFAULT
, Value
);
1824 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
1825 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
1826 IfrCreateDefaultRecord (DefaultSize
, mAllDefaultIdArray
[i
], DefaultOptionOpcode
->Type
, pQuestionNode
->mLineNo
, DefaultOptionOpcode
->Value
);
1828 // Save the new created default in the buffer storage.
1830 IfrAddDefaultToBufferConfig (mAllDefaultIdArray
[i
], pQuestionNode
, DefaultOptionOpcode
->Value
);
1838 // For checkbox, the default with smallest default id is given by the question flag.
1839 // And create the missing defaults with true value.
1841 if (pOpHead
-> OpCode
== EFI_IFR_CHECKBOX_OP
&& !QuestionDefaultInfo
->mIsDefaultOpcode
) {
1842 DefaultSize
= OFFSET_OF (EFI_IFR_DEFAULT
, Value
) + sizeof (BOOLEAN
);
1843 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
1844 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
1845 IfrCreateDefaultRecord (DefaultSize
, mAllDefaultIdArray
[i
], EFI_IFR_TYPE_BOOLEAN
, pQuestionNode
->mLineNo
, CheckBoxDefaultValue
);
1847 // Save the new created default.
1849 IfrAddDefaultToBufferConfig (mAllDefaultIdArray
[i
], pQuestionNode
, CheckBoxDefaultValue
);
1857 // The default with smallest default id is given by the default opcode.
1858 // So create the missing defaults base on the value in the default opcode.
1862 // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.
1864 pDefaultNode
= QuestionDefaultInfo
->mDefaultValueRecord
;
1865 Default
= (EFI_IFR_DEFAULT
*)pDefaultNode
->mIfrBinBuf
;
1867 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1869 gAdjustOpcodeOffset
= pDefaultNode
->mNext
->mOffset
;
1871 if (Default
->Type
== EFI_IFR_TYPE_OTHER
) {
1873 // EFI_IFR_DEFAULT_2 opcode.
1875 // Point to the first expression opcode.
1877 pSNode
= pDefaultNode
->mNext
;
1881 // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)
1883 while (pSNode
!= NULL
&& pSNode
->mNext
!= NULL
&& ScopeCount
!= 0) {
1884 pOpHead
= (EFI_IFR_OP_HEADER
*) pSNode
->mIfrBinBuf
;
1885 if (pOpHead
->Scope
== 1) {
1888 if (pOpHead
->OpCode
== EFI_IFR_END_OP
) {
1892 pSNode
= pSNode
->mNext
;
1900 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
1902 gAdjustOpcodeOffset
= pSNode
->mOffset
;
1904 // Create new default opcode node for missing default.
1906 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
1907 OpcodeNumber
= OpcodeCount
;
1908 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
1909 IfrCreateDefaultRecord (Default
->Header
.Length
, mAllDefaultIdArray
[i
], Default
->Type
, pENode
->mLineNo
, Default
->Value
);
1911 // Point to the first expression opcode node.
1913 pSNode
= pDefaultNode
->mNext
;
1915 // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.
1917 while (pSNode
!= NULL
&& pSNode
->mNext
!= NULL
&& OpcodeNumber
-- != 0) {
1918 pOpHead
= (EFI_IFR_OP_HEADER
*) pSNode
->mIfrBinBuf
;
1919 Obj
= new CIfrObj (pOpHead
->OpCode
, NULL
, pSNode
->mBinBufLen
, FALSE
);
1920 assert (Obj
!= NULL
);
1921 Obj
->SetLineNo (pSNode
->mLineNo
);
1922 ObjBinBuf
= Obj
->GetObjBinAddr
<CHAR8
>();
1923 memcpy (ObjBinBuf
, pSNode
->mIfrBinBuf
, (UINTN
)pSNode
->mBinBufLen
);
1925 pSNode
= pSNode
->mNext
;
1931 // EFI_IFR_DEFAULT opcode.
1933 // Create new default opcode node for missing default.
1935 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
1936 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
1937 IfrCreateDefaultRecord (Default
->Header
.Length
, mAllDefaultIdArray
[i
], Default
->Type
, pDefaultNode
->mLineNo
, Default
->Value
);
1939 // Save the new created default in the buffer storage..
1941 IfrAddDefaultToBufferConfig (mAllDefaultIdArray
[i
], pQuestionNode
, Default
->Value
);
1948 Parse the default information in a question, get the QuestionDefaultInfo.
1950 @param pQuestionNode Point to the question record Node.
1951 @param QuestionDefaultInfo On return, point to the QuestionDefaultInfo.
1954 CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(
1955 IN SIfrRecord
*pQuestionNode
,
1956 OUT QuestionDefaultRecord
*QuestionDefaultInfo
1960 EFI_IFR_ONE_OF_OPTION
*OneofOptionOpcode
;
1961 EFI_IFR_OP_HEADER
*pSOpHead
;
1962 EFI_IFR_CHECKBOX
*CheckBoxOpcode
;
1963 EFI_IFR_DEFAULT
*DefaultOpcode
;
1964 BOOLEAN IsOneOfOpcode
;
1965 UINT16 SmallestDefaultId
;
1968 SmallestDefaultId
= 0xffff;
1969 IsOneOfOpcode
= FALSE
;
1971 pSNode
= pQuestionNode
;
1974 // Parse all the opcodes in the Question.
1976 while (pSNode
!= NULL
) {
1977 pSOpHead
= (EFI_IFR_OP_HEADER
*) pSNode
->mIfrBinBuf
;
1979 // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.
1980 // Scopes may be nested within other scopes.
1981 // When finishing parsing a question, the scope count must be zero.
1983 if (pSOpHead
->Scope
== 1) {
1986 if (pSOpHead
->OpCode
== EFI_IFR_END_OP
) {
1990 // Check whether finishing parsing a question.
1992 if (ScopeCount
== 0) {
1997 // Record the default information in the question.
1999 switch (pSOpHead
->OpCode
) {
2000 case EFI_IFR_ONE_OF_OP
:
2001 IsOneOfOpcode
= TRUE
;
2003 case EFI_IFR_CHECKBOX_OP
:
2005 // The default info of check box may be given by flag.
2006 // So need to check the flag of check box.
2008 CheckBoxOpcode
= (EFI_IFR_CHECKBOX
*)pSNode
->mIfrBinBuf
;
2009 if ((CheckBoxOpcode
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0) {
2011 // Check whether need to update the smallest default id.
2013 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2014 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2017 // Update the QuestionDefaultInfo.
2019 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
2020 if (mAllDefaultIdArray
[i
] == EFI_HII_DEFAULT_CLASS_STANDARD
) {
2021 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
2022 QuestionDefaultInfo
->mDefaultNumber
++;
2023 QuestionDefaultInfo
->mIsDefaultIdExist
[i
] = TRUE
;
2029 if ((CheckBoxOpcode
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0) {
2031 // Check whether need to update the smallest default id.
2033 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2034 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2037 // Update the QuestionDefaultInfo.
2039 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
2040 if (mAllDefaultIdArray
[i
] == EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2041 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
2042 QuestionDefaultInfo
->mDefaultNumber
++;
2043 QuestionDefaultInfo
->mIsDefaultIdExist
[i
] = TRUE
;
2050 case EFI_IFR_ONE_OF_OPTION_OP
:
2051 if (!IsOneOfOpcode
) {
2053 // Only check the option in oneof.
2057 OneofOptionOpcode
= (EFI_IFR_ONE_OF_OPTION
*)pSNode
->mIfrBinBuf
;
2058 if ((OneofOptionOpcode
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0) {
2060 // The option is used as the standard default.
2061 // Check whether need to update the smallest default id and QuestionDefaultInfo.
2063 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2064 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2065 QuestionDefaultInfo
->mDefaultValueRecord
= pSNode
;
2068 // Update the IsDefaultIdExist array in QuestionDefaultInfo.
2070 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
2071 if (mAllDefaultIdArray
[i
] == EFI_HII_DEFAULT_CLASS_STANDARD
) {
2072 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
2073 QuestionDefaultInfo
->mDefaultNumber
++;
2074 QuestionDefaultInfo
->mIsDefaultIdExist
[i
] = TRUE
;
2080 if ((OneofOptionOpcode
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0) {
2082 // This option is used as the manufacture default.
2083 // Check whether need to update the smallest default id and QuestionDefaultInfo.
2085 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2086 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2087 QuestionDefaultInfo
->mDefaultValueRecord
= pSNode
;
2090 // Update the QuestionDefaultInfo.
2092 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++) {
2093 if (mAllDefaultIdArray
[i
] == EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2094 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
2095 QuestionDefaultInfo
->mDefaultNumber
++;
2096 QuestionDefaultInfo
->mIsDefaultIdExist
[i
] = TRUE
;
2103 case EFI_IFR_DEFAULT_OP
:
2104 DefaultOpcode
= (EFI_IFR_DEFAULT
*) pSNode
->mIfrBinBuf
;
2106 // Check whether need to update the smallest default id and QuestionDefaultInfo.
2108 if (SmallestDefaultId
>= DefaultOpcode
->DefaultId
) {
2109 SmallestDefaultId
= DefaultOpcode
->DefaultId
;
2110 QuestionDefaultInfo
->mDefaultValueRecord
= pSNode
;
2111 QuestionDefaultInfo
->mIsDefaultOpcode
= TRUE
;
2114 // Update the QuestionDefaultInfo.
2116 for (UINT8 i
= 0; i
< mAllDefaultTypeCount
; i
++){
2117 if (mAllDefaultIdArray
[i
] == ((EFI_IFR_DEFAULT
*)pSNode
->mIfrBinBuf
)->DefaultId
) {
2118 if (!QuestionDefaultInfo
->mIsDefaultIdExist
[i
]) {
2119 QuestionDefaultInfo
->mDefaultNumber
++;
2120 QuestionDefaultInfo
->mIsDefaultIdExist
[i
] = TRUE
;
2130 // Parse next opcode in this question.
2132 pSNode
= pSNode
->mNext
;
2137 Check or add default for question if need.
2139 This function will check the default info for question.
2140 If the question has default, but the default number < defaultstore opcode number.
2141 will do following two action :
2143 1. if (AutoDefault) will add default for question to support all kinds of defaults.
2144 2. if (CheckDefault) will generate an error to tell user the question misses some default value.
2146 We assume that the two options can not be TRUE at same time.
2147 If they are TRUE at same time, only do the action corresponding to AutoDefault option.
2149 @param AutoDefault Add default for question if needed
2150 @param CheckDefault Check the default info, if missing default, generates an error.
2154 CIfrRecordInfoDB::IfrCheckAddDefaultRecord (
2155 BOOLEAN AutoDefault
,
2156 BOOLEAN CheckDefault
2160 SIfrRecord
*pTailNode
;
2161 SIfrRecord
*pStartAdjustNode
;
2162 EFI_IFR_OP_HEADER
*pOpHead
;
2163 QuestionDefaultRecord QuestionDefaultInfo
;
2164 UINT8 MissingDefaultCount
;
2165 CHAR8 Msg
[MAX_STRING_LEN
] = {0, };
2167 pNode
= mIfrRecordListHead
;
2170 // Record the number and default id of all defaultstore opcode.
2172 IfrGetDefaultStoreInfo ();
2174 while (pNode
!= NULL
) {
2175 pOpHead
= (EFI_IFR_OP_HEADER
*) pNode
->mIfrBinBuf
;
2177 // Check whether is question opcode.
2179 if (CheckQuestionOpCode (pOpHead
->OpCode
)) {
2181 // Initialize some local variables here, because they vary with question.
2182 // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.
2184 memset (&QuestionDefaultInfo
, 0, sizeof (QuestionDefaultRecord
));
2185 pTailNode
= mIfrRecordListTail
;
2187 // Get the QuestionDefaultInfo for current question.
2189 IfrParseDefaulInfoInQuestion (pNode
, &QuestionDefaultInfo
);
2191 if (QuestionDefaultInfo
.mDefaultNumber
!= mAllDefaultTypeCount
&& QuestionDefaultInfo
.mDefaultNumber
!= 0) {
2194 // Create default for question which misses default.
2196 IfrCreateDefaultForQuestion (pNode
, &QuestionDefaultInfo
);
2199 // Adjust the buffer content.
2200 // pStartAdjustNode->mIfrBinBuf points to the insert position.
2201 // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.
2203 pStartAdjustNode
=GetRecordInfoFromOffset (gAdjustOpcodeOffset
);
2204 gCFormPkg
.AdjustDynamicInsertOpcode (pStartAdjustNode
->mIfrBinBuf
, pTailNode
->mNext
->mIfrBinBuf
, TRUE
);
2207 // Update the record info.
2209 IfrUpdateRecordInfoForDynamicOpcode (TRUE
);
2210 } else if (CheckDefault
) {
2212 // Generate an error for question which misses default.
2214 MissingDefaultCount
= mAllDefaultTypeCount
- QuestionDefaultInfo
.mDefaultNumber
;
2215 sprintf (Msg
, "The question misses %d default, the question's opcode is %d", MissingDefaultCount
, pOpHead
->OpCode
);
2216 gCVfrErrorHandle
.PrintMsg (pNode
->mLineNo
, NULL
, "Error", Msg
);
2221 // parse next opcode.
2223 pNode
= pNode
->mNext
;
2227 CIfrRecordInfoDB gCIfrRecordInfoDB
;
2230 CIfrObj::_EMIT_PENDING_OBJ (
2234 CHAR8
*ObjBinBuf
= NULL
;
2239 if (!mDelayEmit
|| !gCreateOp
) {
2243 mPkgOffset
= gCFormPkg
.GetPkgLength ();
2245 // update data buffer to package data
2247 ObjBinBuf
= gCFormPkg
.IfrBinBufferGet (mObjBinLen
);
2248 if (ObjBinBuf
!= NULL
) {
2249 memmove (ObjBinBuf
, mObjBinBuf
, mObjBinLen
);
2253 // update bin buffer to package data buffer
2255 if (mObjBinBuf
!= NULL
) {
2256 delete[] mObjBinBuf
;
2257 mObjBinBuf
= ObjBinBuf
;
2264 * The definition of CIfrObj's member function
2269 } gOpcodeSizesScopeTable
[] = {
2270 { 0, 0 }, // EFI_IFR_INVALID - 0x00
2271 { sizeof (EFI_IFR_FORM
), 1 }, // EFI_IFR_FORM_OP
2272 { sizeof (EFI_IFR_SUBTITLE
), 1 }, // EFI_IFR_SUBTITLE_OP
2273 { sizeof (EFI_IFR_TEXT
), 0 }, // EFI_IFR_TEXT_OP
2274 { sizeof (EFI_IFR_IMAGE
), 0 }, // EFI_IFR_IMAGE_OP
2275 { sizeof (EFI_IFR_ONE_OF
), 1 }, // EFI_IFR_ONE_OF_OP - 0x05
2276 { sizeof (EFI_IFR_CHECKBOX
), 1}, // EFI_IFR_CHECKBOX_OP
2277 { sizeof (EFI_IFR_NUMERIC
), 1 }, // EFI_IFR_NUMERIC_OP
2278 { sizeof (EFI_IFR_PASSWORD
), 1 }, // EFI_IFR_PASSWORD_OP
2279 { sizeof (EFI_IFR_ONE_OF_OPTION
), 0 }, // EFI_IFR_ONE_OF_OPTION_OP
2280 { sizeof (EFI_IFR_SUPPRESS_IF
), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A
2281 { sizeof (EFI_IFR_LOCKED
), 0 }, // EFI_IFR_LOCKED_OP
2282 { sizeof (EFI_IFR_ACTION
), 1 }, // EFI_IFR_ACTION_OP
2283 { sizeof (EFI_IFR_RESET_BUTTON
), 1 }, // EFI_IFR_RESET_BUTTON_OP
2284 { sizeof (EFI_IFR_FORM_SET
), 1 }, // EFI_IFR_FORM_SET_OP -0xE
2285 { sizeof (EFI_IFR_REF
), 0 }, // EFI_IFR_REF_OP
2286 { sizeof (EFI_IFR_NO_SUBMIT_IF
), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10
2287 { sizeof (EFI_IFR_INCONSISTENT_IF
), 1 }, // EFI_IFR_INCONSISTENT_IF_OP
2288 { sizeof (EFI_IFR_EQ_ID_VAL
), 0 }, // EFI_IFR_EQ_ID_VAL_OP
2289 { sizeof (EFI_IFR_EQ_ID_ID
), 0 }, // EFI_IFR_EQ_ID_ID_OP
2290 { sizeof (EFI_IFR_EQ_ID_VAL_LIST
), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14
2291 { sizeof (EFI_IFR_AND
), 0 }, // EFI_IFR_AND_OP
2292 { sizeof (EFI_IFR_OR
), 0 }, // EFI_IFR_OR_OP
2293 { sizeof (EFI_IFR_NOT
), 0 }, // EFI_IFR_NOT_OP
2294 { sizeof (EFI_IFR_RULE
), 1 }, // EFI_IFR_RULE_OP
2295 { sizeof (EFI_IFR_GRAY_OUT_IF
), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19
2296 { sizeof (EFI_IFR_DATE
), 1 }, // EFI_IFR_DATE_OP
2297 { sizeof (EFI_IFR_TIME
), 1 }, // EFI_IFR_TIME_OP
2298 { sizeof (EFI_IFR_STRING
), 1 }, // EFI_IFR_STRING_OP
2299 { sizeof (EFI_IFR_REFRESH
), 0 }, // EFI_IFR_REFRESH_OP
2300 { sizeof (EFI_IFR_DISABLE_IF
), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E
2302 { sizeof (EFI_IFR_TO_LOWER
), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20
2303 { sizeof (EFI_IFR_TO_UPPER
), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21
2304 { sizeof (EFI_IFR_MAP
), 1 }, // EFI_IFR_MAP - 0x22
2305 { sizeof (EFI_IFR_ORDERED_LIST
), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23
2306 { sizeof (EFI_IFR_VARSTORE
), 0 }, // EFI_IFR_VARSTORE_OP
2307 { sizeof (EFI_IFR_VARSTORE_NAME_VALUE
), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP
2308 { sizeof (EFI_IFR_VARSTORE_EFI
), 0 }, // EFI_IFR_VARSTORE_EFI_OP
2309 { sizeof (EFI_IFR_VARSTORE_DEVICE
), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP
2310 { sizeof (EFI_IFR_VERSION
), 0 }, // EFI_IFR_VERSION_OP - 0x28
2311 { sizeof (EFI_IFR_END
), 0 }, // EFI_IFR_END_OP
2312 { sizeof (EFI_IFR_MATCH
), 0 }, // EFI_IFR_MATCH_OP - 0x2A
2313 { sizeof (EFI_IFR_GET
), 0 }, // EFI_IFR_GET - 0x2B
2314 { sizeof (EFI_IFR_SET
), 0 }, // EFI_IFR_SET - 0x2C
2315 { sizeof (EFI_IFR_READ
), 0 }, // EFI_IFR_READ - 0x2D
2316 { sizeof (EFI_IFR_WRITE
), 0 }, // EFI_IFR_WRITE - 0x2E
2317 { sizeof (EFI_IFR_EQUAL
), 0 }, // EFI_IFR_EQUAL_OP - 0x2F
2318 { sizeof (EFI_IFR_NOT_EQUAL
), 0 }, // EFI_IFR_NOT_EQUAL_OP
2319 { sizeof (EFI_IFR_GREATER_THAN
), 0 }, // EFI_IFR_GREATER_THAN_OP
2320 { sizeof (EFI_IFR_GREATER_EQUAL
), 0 }, // EFI_IFR_GREATER_EQUAL_OP
2321 { sizeof (EFI_IFR_LESS_THAN
), 0 }, // EFI_IFR_LESS_THAN_OP
2322 { sizeof (EFI_IFR_LESS_EQUAL
), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34
2323 { sizeof (EFI_IFR_BITWISE_AND
), 0 }, // EFI_IFR_BITWISE_AND_OP
2324 { sizeof (EFI_IFR_BITWISE_OR
), 0 }, // EFI_IFR_BITWISE_OR_OP
2325 { sizeof (EFI_IFR_BITWISE_NOT
), 0 }, // EFI_IFR_BITWISE_NOT_OP
2326 { sizeof (EFI_IFR_SHIFT_LEFT
), 0 }, // EFI_IFR_SHIFT_LEFT_OP
2327 { sizeof (EFI_IFR_SHIFT_RIGHT
), 0 }, // EFI_IFR_SHIFT_RIGHT_OP
2328 { sizeof (EFI_IFR_ADD
), 0 }, // EFI_IFR_ADD_OP - 0x3A
2329 { sizeof (EFI_IFR_SUBTRACT
), 0 }, // EFI_IFR_SUBTRACT_OP
2330 { sizeof (EFI_IFR_MULTIPLY
), 0 }, // EFI_IFR_MULTIPLY_OP
2331 { sizeof (EFI_IFR_DIVIDE
), 0 }, // EFI_IFR_DIVIDE_OP
2332 { sizeof (EFI_IFR_MODULO
), 0 }, // EFI_IFR_MODULO_OP - 0x3E
2333 { sizeof (EFI_IFR_RULE_REF
), 0 }, // EFI_IFR_RULE_REF_OP
2334 { sizeof (EFI_IFR_QUESTION_REF1
), 0 }, // EFI_IFR_QUESTION_REF1_OP
2335 { sizeof (EFI_IFR_QUESTION_REF2
), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41
2336 { sizeof (EFI_IFR_UINT8
), 0}, // EFI_IFR_UINT8
2337 { sizeof (EFI_IFR_UINT16
), 0}, // EFI_IFR_UINT16
2338 { sizeof (EFI_IFR_UINT32
), 0}, // EFI_IFR_UINT32
2339 { sizeof (EFI_IFR_UINT64
), 0}, // EFI_IFR_UTNT64
2340 { sizeof (EFI_IFR_TRUE
), 0 }, // EFI_IFR_TRUE_OP - 0x46
2341 { sizeof (EFI_IFR_FALSE
), 0 }, // EFI_IFR_FALSE_OP
2342 { sizeof (EFI_IFR_TO_UINT
), 0 }, // EFI_IFR_TO_UINT_OP
2343 { sizeof (EFI_IFR_TO_STRING
), 0 }, // EFI_IFR_TO_STRING_OP
2344 { sizeof (EFI_IFR_TO_BOOLEAN
), 0 }, // EFI_IFR_TO_BOOLEAN_OP
2345 { sizeof (EFI_IFR_MID
), 0 }, // EFI_IFR_MID_OP
2346 { sizeof (EFI_IFR_FIND
), 0 }, // EFI_IFR_FIND_OP
2347 { sizeof (EFI_IFR_TOKEN
), 0 }, // EFI_IFR_TOKEN_OP
2348 { sizeof (EFI_IFR_STRING_REF1
), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E
2349 { sizeof (EFI_IFR_STRING_REF2
), 0 }, // EFI_IFR_STRING_REF2_OP
2350 { sizeof (EFI_IFR_CONDITIONAL
), 0 }, // EFI_IFR_CONDITIONAL_OP
2351 { sizeof (EFI_IFR_QUESTION_REF3
), 0 }, // EFI_IFR_QUESTION_REF3_OP
2352 { sizeof (EFI_IFR_ZERO
), 0 }, // EFI_IFR_ZERO_OP
2353 { sizeof (EFI_IFR_ONE
), 0 }, // EFI_IFR_ONE_OP
2354 { sizeof (EFI_IFR_ONES
), 0 }, // EFI_IFR_ONES_OP
2355 { sizeof (EFI_IFR_UNDEFINED
), 0 }, // EFI_IFR_UNDEFINED_OP
2356 { sizeof (EFI_IFR_LENGTH
), 0 }, // EFI_IFR_LENGTH_OP
2357 { sizeof (EFI_IFR_DUP
), 0 }, // EFI_IFR_DUP_OP - 0x57
2358 { sizeof (EFI_IFR_THIS
), 0 }, // EFI_IFR_THIS_OP
2359 { sizeof (EFI_IFR_SPAN
), 0 }, // EFI_IFR_SPAN_OP
2360 { sizeof (EFI_IFR_VALUE
), 1 }, // EFI_IFR_VALUE_OP
2361 { sizeof (EFI_IFR_DEFAULT
), 0 }, // EFI_IFR_DEFAULT_OP
2362 { sizeof (EFI_IFR_DEFAULTSTORE
), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C
2363 { sizeof (EFI_IFR_FORM_MAP
), 1}, // EFI_IFR_FORM_MAP_OP - 0x5D
2364 { sizeof (EFI_IFR_CATENATE
), 0 }, // EFI_IFR_CATENATE_OP
2365 { sizeof (EFI_IFR_GUID
), 0 }, // EFI_IFR_GUID_OP
2366 { sizeof (EFI_IFR_SECURITY
), 0 }, // EFI_IFR_SECURITY_OP - 0x60
2367 { sizeof (EFI_IFR_MODAL_TAG
), 0}, // EFI_IFR_MODAL_TAG_OP - 0x61
2368 { sizeof (EFI_IFR_REFRESH_ID
), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62
2369 { sizeof (EFI_IFR_WARNING_IF
), 1}, // EFI_IFR_WARNING_IF_OP - 0x63
2370 { sizeof (EFI_IFR_MATCH2
), 0 }, // EFI_IFR_MATCH2_OP - 0x64
2373 #ifdef CIFROBJ_DEUBG
2376 } gIfrObjPrintDebugTable
[] = {
2377 "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF",
2378 "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED",
2379 "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF",
2380 "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT",
2381 "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH",
2382 "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_MAP", "EFI_IFR_ORDERED_LIST",
2383 "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END",
2384 "EFI_IFR_MATCH", "EFI_IFR_GET", "EFI_IFR_SET", "EFI_IFR_READ", "EFI_IFR_WRITE", "EFI_IFR_EQUAL",
2385 "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND",
2386 "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT",
2387 "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",
2388 "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE",
2389 "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN",
2390 "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE",
2391 "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN",
2392 "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_FORM_MAP", "EFI_IFR_CATENATE", "EFI_IFR_GUID",
2393 "EFI_IFR_SECURITY", "EFI_IFR_MODAL_TAG", "EFI_IFR_REFRESH_ID", "EFI_IFR_WARNING_IF", "EFI_IFR_MATCH2",
2397 CIFROBJ_DEBUG_PRINT (
2401 printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable
[OpCode
].mIfrName
);
2405 #define CIFROBJ_DEBUG_PRINT(OpCode)
2409 BOOLEAN gCreateOp
= TRUE
;
2415 IN BOOLEAN DelayEmit
2418 mDelayEmit
= DelayEmit
;
2419 mPkgOffset
= gCFormPkg
.GetPkgLength ();
2420 mObjBinLen
= (ObjBinLen
== 0) ? gOpcodeSizesScopeTable
[OpCode
].mSize
: ObjBinLen
;
2421 mObjBinBuf
= ((DelayEmit
== FALSE
) && (gCreateOp
== TRUE
)) ? gCFormPkg
.IfrBinBufferGet (mObjBinLen
) : new CHAR8
[EFI_IFR_MAX_LENGTH
];
2422 mRecordIdx
= (gCreateOp
== TRUE
) ? gCIfrRecordInfoDB
.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf
, mObjBinLen
, mPkgOffset
) : EFI_IFR_RECORDINFO_IDX_INVALUD
;
2425 assert (mObjBinBuf
!= NULL
);
2427 if (IfrObj
!= NULL
) {
2428 *IfrObj
= mObjBinBuf
;
2431 CIFROBJ_DEBUG_PRINT (OpCode
);
2438 if ((mDelayEmit
== TRUE
) && ((gCreateOp
== TRUE
))) {
2439 _EMIT_PENDING_OBJ ();
2442 gCIfrRecordInfoDB
.IfrRecordInfoUpdate (mRecordIdx
, mLineNo
, mObjBinBuf
, mObjBinLen
, mPkgOffset
);
2446 * The definition of CIfrObj's member function
2448 UINT8 gScopeCount
= 0;
2450 CIfrOpHeader::CIfrOpHeader (
2454 ) : mHeader ((EFI_IFR_OP_HEADER
*)StartAddr
)
2456 mHeader
->OpCode
= OpCode
;
2457 mHeader
->Length
= (Length
== 0) ? gOpcodeSizesScopeTable
[OpCode
].mSize
: Length
;
2458 mHeader
->Scope
= (gOpcodeSizesScopeTable
[OpCode
].mScope
+ gScopeCount
> 0) ? 1 : 0;
2461 CIfrOpHeader::CIfrOpHeader (
2462 IN CIfrOpHeader
&OpHdr
2465 mHeader
= OpHdr
.mHeader
;
2468 UINT32
CIfrFormId::FormIdBitMap
[EFI_FREE_FORM_ID_BITMAP_SIZE
] = {0, };