2 Parser for IFR binary encoding.
4 Copyright (c) 2007 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 UINT16 mStatementIndex
;
19 UINT16 mExpressionOpCodeIndex
;
21 BOOLEAN mInScopeSubtitle
;
22 BOOLEAN mInScopeSuppress
;
23 BOOLEAN mInScopeGrayOut
;
24 FORM_EXPRESSION
*mSuppressExpression
;
25 FORM_EXPRESSION
*mGrayOutExpression
;
28 Initialize Statement header members.
30 @param OpCodeData Pointer of the raw OpCode data.
31 @param FormSet Pointer of the current FormSe.
32 @param Form Pointer of the current Form.
34 @return The Statement.
37 FORM_BROWSER_STATEMENT
*
40 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
41 IN OUT FORM_BROWSER_FORM
*Form
44 FORM_BROWSER_STATEMENT
*Statement
;
45 EFI_IFR_STATEMENT_HEADER
*StatementHdr
;
49 // We are currently not in a Form Scope, so just skip this Statement
54 Statement
= &FormSet
->StatementBuffer
[mStatementIndex
];
57 InitializeListHead (&Statement
->DefaultListHead
);
58 InitializeListHead (&Statement
->OptionListHead
);
59 InitializeListHead (&Statement
->InconsistentListHead
);
60 InitializeListHead (&Statement
->NoSubmitListHead
);
62 Statement
->Signature
= FORM_BROWSER_STATEMENT_SIGNATURE
;
64 Statement
->Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
66 StatementHdr
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
67 CopyMem (&Statement
->Prompt
, &StatementHdr
->Prompt
, sizeof (EFI_STRING_ID
));
68 CopyMem (&Statement
->Help
, &StatementHdr
->Help
, sizeof (EFI_STRING_ID
));
70 if (mInScopeSuppress
) {
71 Statement
->SuppressExpression
= mSuppressExpression
;
74 if (mInScopeGrayOut
) {
75 Statement
->GrayOutExpression
= mGrayOutExpression
;
78 Statement
->InSubtitle
= mInScopeSubtitle
;
81 // Insert this Statement into current Form
83 InsertTailList (&Form
->StatementListHead
, &Statement
->Link
);
89 Convert a numeric value to a Unicode String and insert it to String Package.
90 This string is used as the Unicode Name for the EFI Variable. This is to support
91 the deprecated vareqval opcode.
93 @param FormSet The FormSet.
94 @param Statement The numeric question whose VarStoreInfo.VarName is the
95 numeric value which is used to produce the Unicode Name
98 If the Statement is NULL, the ASSERT.
99 If the opcode is not Numeric, then ASSERT.
101 @retval EFI_SUCCESS The funtion always succeeds.
104 UpdateCheckBoxStringToken (
105 IN CONST FORM_BROWSER_FORMSET
*FormSet
,
106 IN FORM_BROWSER_STATEMENT
*Statement
109 CHAR16 Str
[MAXIMUM_VALUE_CHARACTERS
];
113 ASSERT (Statement
!= NULL
);
114 ASSERT (Statement
->Operand
== EFI_IFR_NUMERIC_OP
);
116 UnicodeValueToString (Str
, 0, Statement
->VarStoreInfo
.VarName
, MAXIMUM_VALUE_CHARACTERS
- 1);
118 Status
= HiiLibNewString (FormSet
->HiiHandle
, &Id
, Str
);
120 if (EFI_ERROR (Status
)) {
124 Statement
->VarStoreInfo
.VarName
= Id
;
130 Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.
132 @param OpCodeData The current opcode.
138 IsNextOpCodeGuidedVarEqName (
145 OpCodeData
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
146 if (*OpCodeData
== EFI_IFR_GUID_OP
) {
147 if (CompareGuid (&gEfiIfrFrameworkGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
149 // Specific GUIDed opcodes to support IFR generated from Framework HII VFR
151 if ((((EFI_IFR_GUID_VAREQNAME
*) OpCodeData
)->ExtendOpCode
) == EFI_IFR_EXTEND_OP_VAREQNAME
) {
161 Initialize Question's members.
163 @param OpCodeData Pointer of the raw OpCode data.
164 @param FormSet Pointer of the current FormSet.
165 @param Form Pointer of the current Form.
167 @return The Question.
170 FORM_BROWSER_STATEMENT
*
172 IN UINT8
*OpCodeData
,
173 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
174 IN OUT FORM_BROWSER_FORM
*Form
177 FORM_BROWSER_STATEMENT
*Statement
;
178 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
180 FORMSET_STORAGE
*Storage
;
181 NAME_VALUE_NODE
*NameValueNode
;
184 Statement
= CreateStatement (OpCodeData
, FormSet
, Form
);
185 if (Statement
== NULL
) {
189 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
190 CopyMem (&Statement
->QuestionId
, &QuestionHdr
->QuestionId
, sizeof (EFI_QUESTION_ID
));
191 CopyMem (&Statement
->VarStoreId
, &QuestionHdr
->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
192 CopyMem (&Statement
->VarStoreInfo
.VarOffset
, &QuestionHdr
->VarStoreInfo
.VarOffset
, sizeof (UINT16
));
194 Statement
->QuestionFlags
= QuestionHdr
->Flags
;
196 if (Statement
->VarStoreId
== 0) {
198 // VarStoreId of zero indicates no variable storage
204 // Take a look at next OpCode to see whether it is a GUIDed opcode to support
205 // Framework Compatibility
207 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
208 if ((*OpCodeData
== EFI_IFR_NUMERIC_OP
) && IsNextOpCodeGuidedVarEqName (OpCodeData
)) {
209 Status
= UpdateCheckBoxStringToken (FormSet
, Statement
);
210 if (EFI_ERROR (Status
)) {
217 // Find Storage for this Question
219 Link
= GetFirstNode (&FormSet
->StorageListHead
);
220 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
221 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
223 if (Storage
->VarStoreId
== Statement
->VarStoreId
) {
224 Statement
->Storage
= Storage
;
228 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
230 ASSERT (Statement
->Storage
!= NULL
);
233 // Initialilze varname for Name/Value or EFI Variable
235 if ((Statement
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) ||
236 (Statement
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
237 Statement
->VariableName
= GetToken (Statement
->VarStoreInfo
.VarName
, FormSet
->HiiHandle
);
238 ASSERT (Statement
->VariableName
!= NULL
);
240 if (Statement
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
242 // Insert to Name/Value varstore list
244 NameValueNode
= AllocateZeroPool (sizeof (NAME_VALUE_NODE
));
245 ASSERT (NameValueNode
!= NULL
);
246 NameValueNode
->Signature
= NAME_VALUE_NODE_SIGNATURE
;
247 NameValueNode
->Name
= AllocateCopyPool (StrSize (Statement
->VariableName
), Statement
->VariableName
);
248 ASSERT (NameValueNode
->Name
!= NULL
);
249 NameValueNode
->Value
= AllocateZeroPool (0x10);
250 ASSERT (NameValueNode
->Value
!= NULL
);
251 NameValueNode
->EditValue
= AllocateZeroPool (0x10);
252 ASSERT (NameValueNode
->EditValue
!= NULL
);
254 InsertTailList (&Statement
->Storage
->NameValueListHead
, &NameValueNode
->Link
);
263 Allocate a FORM_EXPRESSION node.
265 @param Form The Form associated with this Expression
267 @return Pointer to a FORM_EXPRESSION data structure.
272 IN OUT FORM_BROWSER_FORM
*Form
275 FORM_EXPRESSION
*Expression
;
277 Expression
= AllocateZeroPool (sizeof (FORM_EXPRESSION
));
278 ASSERT (Expression
!= NULL
);
279 Expression
->Signature
= FORM_EXPRESSION_SIGNATURE
;
280 InitializeListHead (&Expression
->OpCodeListHead
);
287 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
289 @param FormSet Pointer of the current FormSet
291 @return Pointer to a FORMSET_STORAGE data structure.
296 IN FORM_BROWSER_FORMSET
*FormSet
299 FORMSET_STORAGE
*Storage
;
301 Storage
= AllocateZeroPool (sizeof (FORMSET_STORAGE
));
302 ASSERT (Storage
!= NULL
);
303 Storage
->Signature
= FORMSET_STORAGE_SIGNATURE
;
304 InitializeListHead (&Storage
->NameValueListHead
);
305 InsertTailList (&FormSet
->StorageListHead
, &Storage
->Link
);
312 Create ConfigHdr string for a storage.
314 @param FormSet Pointer of the current FormSet
315 @param Storage Pointer of the storage
317 @retval EFI_SUCCESS Initialize ConfigHdr success
321 InitializeConfigHdr (
322 IN FORM_BROWSER_FORMSET
*FormSet
,
323 IN OUT FORMSET_STORAGE
*Storage
328 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
329 Name
= Storage
->Name
;
334 Storage
->ConfigHdr
= HiiConstructConfigHdr (
337 FormSet
->DriverHandle
340 if (Storage
->ConfigHdr
== NULL
) {
341 return EFI_NOT_FOUND
;
344 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigHdr
), Storage
->ConfigHdr
);
345 Storage
->SpareStrLen
= 0;
352 Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
354 @param FormSet Pointer of the current FormSet.
355 @param Question The Question to be initialized.
357 @retval EFI_SUCCESS Function success.
358 @retval EFI_INVALID_PARAMETER No storage associated with the Question.
362 InitializeRequestElement (
363 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
364 IN OUT FORM_BROWSER_STATEMENT
*Question
367 FORMSET_STORAGE
*Storage
;
371 CHAR16 RequestElement
[30];
373 Storage
= Question
->Storage
;
374 if (Storage
== NULL
) {
375 return EFI_INVALID_PARAMETER
;
378 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
380 // <ConfigRequest> is unnecessary for EFI variable storage,
381 // GetVariable()/SetVariable() will be used to retrieve/save values
387 // Prepare <RequestElement>
389 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
390 StrLen
= UnicodeSPrint (
392 30 * sizeof (CHAR16
),
393 L
"&OFFSET=%x&WIDTH=%x",
394 Question
->VarStoreInfo
.VarOffset
,
395 Question
->StorageWidth
397 Question
->BlockName
= AllocateCopyPool ((StrLen
+ 1) * sizeof (CHAR16
), RequestElement
);
399 StrLen
= UnicodeSPrint (RequestElement
, 30 * sizeof (CHAR16
), L
"&%s", Question
->VariableName
);
402 if ((Question
->Operand
== EFI_IFR_PASSWORD_OP
) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
404 // Password with CALLBACK flag is stored in encoded format,
405 // so don't need to append it to <ConfigRequest>
411 // Append <RequestElement> to <ConfigRequest>
413 if (StrLen
> Storage
->SpareStrLen
) {
415 // Old String buffer is not sufficient for RequestElement, allocate a new one
417 StringSize
= (Storage
->ConfigRequest
!= NULL
) ? StrSize (Storage
->ConfigRequest
) : sizeof (CHAR16
);
418 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
419 ASSERT (NewStr
!= NULL
);
420 if (Storage
->ConfigRequest
!= NULL
) {
421 CopyMem (NewStr
, Storage
->ConfigRequest
, StringSize
);
422 FreePool (Storage
->ConfigRequest
);
424 Storage
->ConfigRequest
= NewStr
;
425 Storage
->SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
428 StrCat (Storage
->ConfigRequest
, RequestElement
);
429 Storage
->ElementCount
++;
430 Storage
->SpareStrLen
-= StrLen
;
437 Free resources of a Expression.
439 @param FormSet Pointer of the Expression
444 IN FORM_EXPRESSION
*Expression
448 EXPRESSION_OPCODE
*OpCode
;
450 while (!IsListEmpty (&Expression
->OpCodeListHead
)) {
451 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
452 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
453 RemoveEntryList (&OpCode
->Link
);
455 if (OpCode
->ValueList
!= NULL
) {
456 FreePool (OpCode
->ValueList
);
461 // Free this Expression
463 FreePool (Expression
);
468 Free resources of a storage.
470 @param Storage Pointer of the storage
475 IN FORMSET_STORAGE
*Storage
479 NAME_VALUE_NODE
*NameValueNode
;
481 if (Storage
== NULL
) {
485 if (Storage
->Name
!= NULL
) {
486 FreePool (Storage
->Name
);
488 if (Storage
->Buffer
!= NULL
) {
489 FreePool (Storage
->Buffer
);
491 if (Storage
->EditBuffer
!= NULL
) {
492 FreePool (Storage
->EditBuffer
);
495 while (!IsListEmpty (&Storage
->NameValueListHead
)) {
496 Link
= GetFirstNode (&Storage
->NameValueListHead
);
497 NameValueNode
= NAME_VALUE_NODE_FROM_LINK (Link
);
498 RemoveEntryList (&NameValueNode
->Link
);
500 if (NameValueNode
->Name
!= NULL
) {
501 FreePool (NameValueNode
->Name
);
503 if (NameValueNode
->Value
!= NULL
) {
504 FreePool (NameValueNode
->Value
);
506 if (NameValueNode
->EditValue
!= NULL
) {
507 FreePool (NameValueNode
->EditValue
);
509 FreePool (NameValueNode
);
512 if (Storage
->ConfigHdr
!= NULL
) {
513 FreePool (Storage
->ConfigHdr
);
515 if (Storage
->ConfigRequest
!= NULL
) {
516 FreePool (Storage
->ConfigRequest
);
524 Free resources of a Statement.
526 @param Statement Pointer of the Statement
531 IN OUT FORM_BROWSER_STATEMENT
*Statement
535 QUESTION_DEFAULT
*Default
;
536 QUESTION_OPTION
*Option
;
537 FORM_EXPRESSION
*Expression
;
540 // Free Default value List
542 while (!IsListEmpty (&Statement
->DefaultListHead
)) {
543 Link
= GetFirstNode (&Statement
->DefaultListHead
);
544 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
545 RemoveEntryList (&Default
->Link
);
553 while (!IsListEmpty (&Statement
->OptionListHead
)) {
554 Link
= GetFirstNode (&Statement
->OptionListHead
);
555 Option
= QUESTION_OPTION_FROM_LINK (Link
);
556 RemoveEntryList (&Option
->Link
);
562 // Free Inconsistent List
564 while (!IsListEmpty (&Statement
->InconsistentListHead
)) {
565 Link
= GetFirstNode (&Statement
->InconsistentListHead
);
566 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
567 RemoveEntryList (&Expression
->Link
);
569 DestroyExpression (Expression
);
573 // Free NoSubmit List
575 while (!IsListEmpty (&Statement
->NoSubmitListHead
)) {
576 Link
= GetFirstNode (&Statement
->NoSubmitListHead
);
577 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
578 RemoveEntryList (&Expression
->Link
);
580 DestroyExpression (Expression
);
583 if (Statement
->VariableName
!= NULL
) {
584 FreePool (Statement
->VariableName
);
586 if (Statement
->BlockName
!= NULL
) {
587 FreePool (Statement
->BlockName
);
593 Free resources of a Form.
595 @param Form Pointer of the Form.
600 IN OUT FORM_BROWSER_FORM
*Form
604 FORM_EXPRESSION
*Expression
;
605 FORM_BROWSER_STATEMENT
*Statement
;
608 // Free Form Expressions
610 while (!IsListEmpty (&Form
->ExpressionListHead
)) {
611 Link
= GetFirstNode (&Form
->ExpressionListHead
);
612 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
613 RemoveEntryList (&Expression
->Link
);
615 DestroyExpression (Expression
);
619 // Free Statements/Questions
621 while (!IsListEmpty (&Form
->StatementListHead
)) {
622 Link
= GetFirstNode (&Form
->StatementListHead
);
623 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
624 RemoveEntryList (&Statement
->Link
);
626 DestroyStatement (Statement
);
637 Free resources allocated for a FormSet.
639 @param FormSet Pointer of the FormSet
644 IN OUT FORM_BROWSER_FORMSET
*FormSet
648 FORMSET_STORAGE
*Storage
;
649 FORMSET_DEFAULTSTORE
*DefaultStore
;
650 FORM_BROWSER_FORM
*Form
;
653 // Free IFR binary buffer
655 FreePool (FormSet
->IfrBinaryData
);
658 // Free FormSet Storage
660 if (FormSet
->StorageListHead
.ForwardLink
!= NULL
) {
661 while (!IsListEmpty (&FormSet
->StorageListHead
)) {
662 Link
= GetFirstNode (&FormSet
->StorageListHead
);
663 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
664 RemoveEntryList (&Storage
->Link
);
666 DestroyStorage (Storage
);
671 // Free FormSet Default Store
673 if (FormSet
->DefaultStoreListHead
.ForwardLink
!= NULL
) {
674 while (!IsListEmpty (&FormSet
->DefaultStoreListHead
)) {
675 Link
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
676 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (Link
);
677 RemoveEntryList (&DefaultStore
->Link
);
679 FreePool (DefaultStore
);
686 if (FormSet
->FormListHead
.ForwardLink
!= NULL
) {
687 while (!IsListEmpty (&FormSet
->FormListHead
)) {
688 Link
= GetFirstNode (&FormSet
->FormListHead
);
689 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
690 RemoveEntryList (&Form
->Link
);
696 if (FormSet
->StatementBuffer
!= NULL
) {
697 FreePool (FormSet
->StatementBuffer
);
699 if (FormSet
->ExpressionBuffer
!= NULL
) {
700 FreePool (FormSet
->ExpressionBuffer
);
708 Tell whether this Operand is an Expression OpCode or not
710 @param Operand Operand of an IFR OpCode.
712 @retval TRUE This is an Expression OpCode.
713 @retval FALSE Not an Expression OpCode.
721 if (((Operand
>= EFI_IFR_EQ_ID_VAL_OP
) && (Operand
<= EFI_IFR_NOT_OP
)) ||
722 ((Operand
>= EFI_IFR_MATCH_OP
) && (Operand
<= EFI_IFR_SPAN_OP
)) ||
723 (Operand
== EFI_IFR_CATENATE_OP
) ||
724 (Operand
== EFI_IFR_TO_LOWER_OP
) ||
725 (Operand
== EFI_IFR_TO_UPPER_OP
) ||
726 (Operand
== EFI_IFR_VERSION_OP
)
736 Calculate number of Statemens(Questions) and Expression OpCodes.
738 @param FormSet The FormSet to be counted.
739 @param NumberOfStatement Number of Statemens(Questions)
740 @param NumberOfExpression Number of Expression OpCodes
745 IN FORM_BROWSER_FORMSET
*FormSet
,
746 IN OUT UINT16
*NumberOfStatement
,
747 IN OUT UINT16
*NumberOfExpression
750 UINT16 StatementCount
;
751 UINT16 ExpressionCount
;
760 while (Offset
< FormSet
->IfrBinaryLength
) {
761 OpCodeData
= FormSet
->IfrBinaryData
+ Offset
;
762 OpCodeLen
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
765 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
)) {
772 *NumberOfStatement
= StatementCount
;
773 *NumberOfExpression
= ExpressionCount
;
779 Parse opcodes in the formset IFR binary.
781 @param FormSet Pointer of the FormSet data structure.
783 @retval EFI_SUCCESS Opcode parse success.
784 @retval Other Opcode parse fail.
789 IN FORM_BROWSER_FORMSET
*FormSet
794 FORM_BROWSER_FORM
*CurrentForm
;
795 FORM_BROWSER_STATEMENT
*CurrentStatement
;
796 EXPRESSION_OPCODE
*ExpressionOpCode
;
797 FORM_EXPRESSION
*CurrentExpression
;
804 FORMSET_STORAGE
*Storage
;
805 FORMSET_DEFAULTSTORE
*DefaultStore
;
806 QUESTION_DEFAULT
*CurrentDefault
;
807 QUESTION_OPTION
*CurrentOption
;
809 UINT16 NumberOfStatement
;
810 UINT16 NumberOfExpression
;
811 EFI_IMAGE_ID
*ImageId
;
812 BOOLEAN SuppressForOption
;
813 BOOLEAN InScopeOptionSuppress
;
814 FORM_EXPRESSION
*OptionSuppressExpression
;
815 BOOLEAN InScopeDisable
;
816 UINT16 DepthOfDisable
;
817 BOOLEAN OpCodeDisabled
;
818 BOOLEAN SingleOpCodeExpression
;
819 BOOLEAN InScopeDefault
;
820 EFI_HII_VALUE
*Value
;
822 mInScopeSubtitle
= FALSE
;
823 SuppressForOption
= FALSE
;
824 mInScopeSuppress
= FALSE
;
825 InScopeOptionSuppress
= FALSE
;
826 mInScopeGrayOut
= FALSE
;
827 InScopeDisable
= FALSE
;
829 OpCodeDisabled
= FALSE
;
830 SingleOpCodeExpression
= FALSE
;
831 InScopeDefault
= FALSE
;
832 CurrentExpression
= NULL
;
833 CurrentDefault
= NULL
;
834 CurrentOption
= NULL
;
835 OptionSuppressExpression
= NULL
;
839 // Get the number of Statements and Expressions
841 CountOpCodes (FormSet
, &NumberOfStatement
, &NumberOfExpression
);
844 FormSet
->StatementBuffer
= AllocateZeroPool (NumberOfStatement
* sizeof (FORM_BROWSER_STATEMENT
));
845 if (FormSet
->StatementBuffer
== NULL
) {
846 return EFI_OUT_OF_RESOURCES
;
849 mExpressionOpCodeIndex
= 0;
850 FormSet
->ExpressionBuffer
= AllocateZeroPool (NumberOfExpression
* sizeof (EXPRESSION_OPCODE
));
851 if (FormSet
->ExpressionBuffer
== NULL
) {
852 return EFI_OUT_OF_RESOURCES
;
855 InitializeListHead (&FormSet
->StorageListHead
);
856 InitializeListHead (&FormSet
->DefaultStoreListHead
);
857 InitializeListHead (&FormSet
->FormListHead
);
860 CurrentStatement
= NULL
;
865 while (OpCodeOffset
< FormSet
->IfrBinaryLength
) {
866 OpCodeData
= FormSet
->IfrBinaryData
+ OpCodeOffset
;
868 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
869 OpCodeOffset
+= OpCodeLength
;
870 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
871 Scope
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Scope
;
874 // If scope bit set, push onto scope stack
880 if (OpCodeDisabled
) {
882 // DisableIf Expression is evaluated to be TRUE, try to find its end.
883 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
885 if (Operand
== EFI_IFR_DISABLE_IF_OP
) {
887 } else if (Operand
== EFI_IFR_END_OP
) {
888 Status
= PopScope (&ScopeOpCode
);
889 if (EFI_ERROR (Status
)) {
893 if (ScopeOpCode
== EFI_IFR_DISABLE_IF_OP
) {
894 if (DepthOfDisable
== 0) {
895 InScopeDisable
= FALSE
;
896 OpCodeDisabled
= FALSE
;
905 if (IsExpressionOpCode (Operand
)) {
906 ExpressionOpCode
= &FormSet
->ExpressionBuffer
[mExpressionOpCodeIndex
];
907 mExpressionOpCodeIndex
++;
909 ExpressionOpCode
->Signature
= EXPRESSION_OPCODE_SIGNATURE
;
910 ExpressionOpCode
->Operand
= Operand
;
911 Value
= &ExpressionOpCode
->Value
;
914 case EFI_IFR_EQ_ID_VAL_OP
:
915 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_VAL
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
917 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
918 CopyMem (&Value
->Value
.u16
, &((EFI_IFR_EQ_ID_VAL
*) OpCodeData
)->Value
, sizeof (UINT16
));
921 case EFI_IFR_EQ_ID_ID_OP
:
922 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_ID
*) OpCodeData
)->QuestionId1
, sizeof (EFI_QUESTION_ID
));
923 CopyMem (&ExpressionOpCode
->QuestionId2
, &((EFI_IFR_EQ_ID_ID
*) OpCodeData
)->QuestionId2
, sizeof (EFI_QUESTION_ID
));
926 case EFI_IFR_EQ_ID_LIST_OP
:
927 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_LIST
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
928 CopyMem (&ExpressionOpCode
->ListLength
, &((EFI_IFR_EQ_ID_LIST
*) OpCodeData
)->ListLength
, sizeof (UINT16
));
929 ExpressionOpCode
->ValueList
= AllocateCopyPool (ExpressionOpCode
->ListLength
* sizeof (UINT16
), &((EFI_IFR_EQ_ID_LIST
*) OpCodeData
)->ValueList
);
932 case EFI_IFR_TO_STRING_OP
:
933 case EFI_IFR_FIND_OP
:
934 ExpressionOpCode
->Format
= (( EFI_IFR_TO_STRING
*) OpCodeData
)->Format
;
937 case EFI_IFR_STRING_REF1_OP
:
938 Value
->Type
= EFI_IFR_TYPE_STRING
;
939 CopyMem (&Value
->Value
.string
, &(( EFI_IFR_STRING_REF1
*) OpCodeData
)->StringId
, sizeof (EFI_STRING_ID
));
942 case EFI_IFR_RULE_REF_OP
:
943 ExpressionOpCode
->RuleId
= (( EFI_IFR_RULE_REF
*) OpCodeData
)->RuleId
;
946 case EFI_IFR_SPAN_OP
:
947 ExpressionOpCode
->Flags
= (( EFI_IFR_SPAN
*) OpCodeData
)->Flags
;
950 case EFI_IFR_THIS_OP
:
951 ASSERT (CurrentStatement
!= NULL
);
952 ExpressionOpCode
->QuestionId
= CurrentStatement
->QuestionId
;
955 case EFI_IFR_QUESTION_REF1_OP
:
956 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_LIST
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
959 case EFI_IFR_QUESTION_REF3_OP
:
960 if (OpCodeLength
>= sizeof (EFI_IFR_QUESTION_REF3_2
)) {
961 CopyMem (&ExpressionOpCode
->DevicePath
, &(( EFI_IFR_QUESTION_REF3_2
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
963 if (OpCodeLength
>= sizeof (EFI_IFR_QUESTION_REF3_3
)) {
964 CopyMem (&ExpressionOpCode
->Guid
, &(( EFI_IFR_QUESTION_REF3_3
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
972 case EFI_IFR_TRUE_OP
:
973 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
974 Value
->Value
.b
= TRUE
;
977 case EFI_IFR_FALSE_OP
:
978 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
979 Value
->Value
.b
= FALSE
;
983 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
987 case EFI_IFR_ZERO_OP
:
988 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
992 case EFI_IFR_ONES_OP
:
993 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
994 Value
->Value
.u64
= 0xffffffffffffffffULL
;
997 case EFI_IFR_UINT8_OP
:
998 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
999 Value
->Value
.u8
= (( EFI_IFR_UINT8
*) OpCodeData
)->Value
;
1002 case EFI_IFR_UINT16_OP
:
1003 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1004 CopyMem (&Value
->Value
.u16
, &(( EFI_IFR_UINT16
*) OpCodeData
)->Value
, sizeof (UINT16
));
1007 case EFI_IFR_UINT32_OP
:
1008 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
1009 CopyMem (&Value
->Value
.u32
, &(( EFI_IFR_UINT32
*) OpCodeData
)->Value
, sizeof (UINT32
));
1012 case EFI_IFR_UINT64_OP
:
1013 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1014 CopyMem (&Value
->Value
.u64
, &(( EFI_IFR_UINT64
*) OpCodeData
)->Value
, sizeof (UINT64
));
1017 case EFI_IFR_UNDEFINED_OP
:
1018 Value
->Type
= EFI_IFR_TYPE_OTHER
;
1021 case EFI_IFR_VERSION_OP
:
1022 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1023 Value
->Value
.u16
= EFI_IFR_SPECIFICATION_VERSION
;
1030 InsertTailList (&CurrentExpression
->OpCodeListHead
, &ExpressionOpCode
->Link
);
1032 if (SingleOpCodeExpression
) {
1034 // There are two cases to indicate the end of an Expression:
1035 // for single OpCode expression: one Expression OpCode
1036 // for expression consists of more than one OpCode: EFI_IFR_END
1038 SingleOpCodeExpression
= FALSE
;
1040 if (InScopeDisable
) {
1042 // Evaluate DisableIf expression
1044 Status
= EvaluateExpression (FormSet
, CurrentForm
, CurrentExpression
);
1045 if (EFI_ERROR (Status
)) {
1049 ASSERT (CurrentExpression
!= NULL
);
1050 if (CurrentExpression
->Result
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1051 return EFI_INVALID_PARAMETER
;
1054 OpCodeDisabled
= CurrentExpression
->Result
.Value
.b
;
1057 CurrentExpression
= NULL
;
1068 case EFI_IFR_FORM_SET_OP
:
1070 // check the formset GUID
1072 if (CompareMem (&FormSet
->Guid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
)) != 0) {
1073 return EFI_INVALID_PARAMETER
;
1076 CopyMem (&FormSet
->FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
1077 CopyMem (&FormSet
->Help
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
1080 case EFI_IFR_FORM_OP
:
1082 // Create a new Form for this FormSet
1084 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
1085 ASSERT (CurrentForm
!= NULL
);
1086 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
1087 InitializeListHead (&CurrentForm
->ExpressionListHead
);
1088 InitializeListHead (&CurrentForm
->StatementListHead
);
1090 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
1091 CopyMem (&CurrentForm
->FormTitle
, &((EFI_IFR_FORM
*) OpCodeData
)->FormTitle
, sizeof (EFI_STRING_ID
));
1094 // Insert into Form list of this FormSet
1096 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
1102 case EFI_IFR_VARSTORE_OP
:
1104 // Create a buffer Storage for this FormSet
1106 Storage
= CreateStorage (FormSet
);
1107 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
1109 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1110 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1111 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
1113 Storage
->Buffer
= AllocateZeroPool (Storage
->Size
);
1114 Storage
->EditBuffer
= AllocateZeroPool (Storage
->Size
);
1116 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
1117 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
1118 ASSERT (Storage
->Name
!= NULL
);
1119 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1120 Storage
->Name
[Index
] = (CHAR16
) AsciiString
[Index
];
1124 // Initialize <ConfigHdr>
1126 InitializeConfigHdr (FormSet
, Storage
);
1129 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1131 // Create a name/value Storage for this FormSet
1133 Storage
= CreateStorage (FormSet
);
1134 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1136 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1137 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1140 // Initialize <ConfigHdr>
1142 InitializeConfigHdr (FormSet
, Storage
);
1145 case EFI_IFR_VARSTORE_EFI_OP
:
1147 // Create a EFI variable Storage for this FormSet
1149 Storage
= CreateStorage (FormSet
);
1150 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
1152 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1153 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1154 CopyMem (&Storage
->Attributes
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Attributes
, sizeof (UINT32
));
1160 case EFI_IFR_DEFAULTSTORE_OP
:
1161 DefaultStore
= AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE
));
1162 ASSERT (DefaultStore
!= NULL
);
1163 DefaultStore
->Signature
= FORMSET_DEFAULTSTORE_SIGNATURE
;
1165 CopyMem (&DefaultStore
->DefaultId
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
1166 CopyMem (&DefaultStore
->DefaultName
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultName
, sizeof (EFI_STRING_ID
));
1169 // Insert to DefaultStore list of this Formset
1171 InsertTailList (&FormSet
->DefaultStoreListHead
, &DefaultStore
->Link
);
1177 case EFI_IFR_SUBTITLE_OP
:
1178 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
1179 ASSERT (CurrentStatement
!= NULL
);
1181 CurrentStatement
->Flags
= ((EFI_IFR_SUBTITLE
*) OpCodeData
)->Flags
;
1184 mInScopeSubtitle
= TRUE
;
1188 case EFI_IFR_TEXT_OP
:
1189 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
1190 ASSERT (CurrentStatement
!= NULL
);
1192 CopyMem (&CurrentStatement
->TextTwo
, &((EFI_IFR_TEXT
*) OpCodeData
)->TextTwo
, sizeof (EFI_STRING_ID
));
1198 case EFI_IFR_ACTION_OP
:
1199 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1200 ASSERT (CurrentStatement
!= NULL
);
1202 if (OpCodeLength
== sizeof (EFI_IFR_ACTION_1
)) {
1204 // No QuestionConfig present, so no configuration string will be processed
1206 CurrentStatement
->QuestionConfig
= 0;
1208 CopyMem (&CurrentStatement
->QuestionConfig
, &((EFI_IFR_ACTION
*) OpCodeData
)->QuestionConfig
, sizeof (EFI_STRING_ID
));
1212 case EFI_IFR_RESET_BUTTON_OP
:
1213 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1215 CopyMem (&CurrentStatement
->DefaultId
, &((EFI_IFR_RESET_BUTTON
*) OpCodeData
)->DefaultId
, sizeof (EFI_DEFAULT_ID
));
1218 case EFI_IFR_REF_OP
:
1219 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1221 CopyMem (&CurrentStatement
->RefFormId
, &((EFI_IFR_REF
*) OpCodeData
)->FormId
, sizeof (EFI_FORM_ID
));
1222 if (OpCodeLength
>= sizeof (EFI_IFR_REF2
)) {
1223 CopyMem (&CurrentStatement
->RefQuestionId
, &((EFI_IFR_REF2
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
1225 if (OpCodeLength
>= sizeof (EFI_IFR_REF3
)) {
1226 CopyMem (&CurrentStatement
->RefFormSetId
, &((EFI_IFR_REF3
*) OpCodeData
)->FormSetId
, sizeof (EFI_GUID
));
1228 if (OpCodeLength
>= sizeof (EFI_IFR_REF4
)) {
1229 CopyMem (&CurrentStatement
->RefDevicePath
, &((EFI_IFR_REF4
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
1235 case EFI_IFR_ONE_OF_OP
:
1236 case EFI_IFR_NUMERIC_OP
:
1237 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1239 CurrentStatement
->Flags
= ((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
;
1240 Value
= &CurrentStatement
->HiiValue
;
1242 switch (CurrentStatement
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1243 case EFI_IFR_NUMERIC_SIZE_1
:
1244 CurrentStatement
->Minimum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MinValue
;
1245 CurrentStatement
->Maximum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MaxValue
;
1246 CurrentStatement
->Step
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.Step
;
1247 CurrentStatement
->StorageWidth
= sizeof (UINT8
);
1248 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1251 case EFI_IFR_NUMERIC_SIZE_2
:
1252 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MinValue
, sizeof (UINT16
));
1253 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MaxValue
, sizeof (UINT16
));
1254 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.Step
, sizeof (UINT16
));
1255 CurrentStatement
->StorageWidth
= sizeof (UINT16
);
1256 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1259 case EFI_IFR_NUMERIC_SIZE_4
:
1260 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MinValue
, sizeof (UINT32
));
1261 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MaxValue
, sizeof (UINT32
));
1262 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.Step
, sizeof (UINT32
));
1263 CurrentStatement
->StorageWidth
= sizeof (UINT32
);
1264 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
1267 case EFI_IFR_NUMERIC_SIZE_8
:
1268 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MinValue
, sizeof (UINT64
));
1269 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MaxValue
, sizeof (UINT64
));
1270 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.Step
, sizeof (UINT64
));
1271 CurrentStatement
->StorageWidth
= sizeof (UINT64
);
1272 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1279 InitializeRequestElement (FormSet
, CurrentStatement
);
1281 if ((Operand
== EFI_IFR_ONE_OF_OP
) && Scope
!= 0) {
1282 SuppressForOption
= TRUE
;
1286 case EFI_IFR_ORDERED_LIST_OP
:
1287 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1289 CurrentStatement
->Flags
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Flags
;
1290 CurrentStatement
->MaxContainers
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1291 CurrentStatement
->StorageWidth
= (UINT16
)(CurrentStatement
->MaxContainers
* sizeof (UINT8
));
1292 InitializeRequestElement (FormSet
, CurrentStatement
);
1295 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
1296 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
1297 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
1299 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_OTHER
;
1300 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
1303 SuppressForOption
= TRUE
;
1307 case EFI_IFR_CHECKBOX_OP
:
1308 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1310 CurrentStatement
->Flags
= ((EFI_IFR_CHECKBOX
*) OpCodeData
)->Flags
;
1311 CurrentStatement
->StorageWidth
= sizeof (BOOLEAN
);
1312 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_BOOLEAN
;
1314 InitializeRequestElement (FormSet
, CurrentStatement
);
1318 case EFI_IFR_STRING_OP
:
1319 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1322 // MinSize is the minimum number of characters that can be accepted for this opcode,
1323 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1324 // The characters are stored as Unicode, so the storage width should multiply 2.
1326 CurrentStatement
->Minimum
= ((EFI_IFR_STRING
*) OpCodeData
)->MinSize
;
1327 CurrentStatement
->Maximum
= ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
;
1328 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (CHAR16
));
1329 CurrentStatement
->Flags
= ((EFI_IFR_STRING
*) OpCodeData
)->Flags
;
1331 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
1332 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
+ sizeof (CHAR16
));
1334 InitializeRequestElement (FormSet
, CurrentStatement
);
1337 case EFI_IFR_PASSWORD_OP
:
1338 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1341 // MinSize is the minimum number of characters that can be accepted for this opcode,
1342 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1343 // The characters are stored as Unicode, so the storage width should multiply 2.
1345 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MinSize
, sizeof (UINT16
));
1346 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
, sizeof (UINT16
));
1347 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (CHAR16
));
1349 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
1350 CurrentStatement
->BufferValue
= AllocateZeroPool ((CurrentStatement
->StorageWidth
+ sizeof (CHAR16
)));
1352 InitializeRequestElement (FormSet
, CurrentStatement
);
1355 case EFI_IFR_DATE_OP
:
1356 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1358 CurrentStatement
->Flags
= ((EFI_IFR_DATE
*) OpCodeData
)->Flags
;
1359 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_DATE
;
1361 if ((CurrentStatement
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_NORMAL
) {
1362 CurrentStatement
->StorageWidth
= sizeof (EFI_HII_DATE
);
1364 InitializeRequestElement (FormSet
, CurrentStatement
);
1367 // Don't assign storage for RTC type of date/time
1369 CurrentStatement
->Storage
= NULL
;
1370 CurrentStatement
->StorageWidth
= 0;
1374 case EFI_IFR_TIME_OP
:
1375 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1377 CurrentStatement
->Flags
= ((EFI_IFR_TIME
*) OpCodeData
)->Flags
;
1378 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_TIME
;
1380 if ((CurrentStatement
->Flags
& QF_TIME_STORAGE
) == QF_TIME_STORAGE_NORMAL
) {
1381 CurrentStatement
->StorageWidth
= sizeof (EFI_IFR_TIME
);
1383 InitializeRequestElement (FormSet
, CurrentStatement
);
1386 // Don't assign storage for RTC type of date/time
1388 CurrentStatement
->Storage
= NULL
;
1389 CurrentStatement
->StorageWidth
= 0;
1396 case EFI_IFR_DEFAULT_OP
:
1398 // EFI_IFR_DEFAULT appear in scope of a Question,
1399 // It creates a default value for the current question.
1400 // A Question may have more than one Default value which have different default types.
1402 CurrentDefault
= AllocateZeroPool (sizeof (QUESTION_DEFAULT
));
1403 ASSERT (CurrentDefault
!= NULL
);
1404 CurrentDefault
->Signature
= QUESTION_DEFAULT_SIGNATURE
;
1406 CurrentDefault
->Value
.Type
= ((EFI_IFR_DEFAULT
*) OpCodeData
)->Type
;
1407 CopyMem (&CurrentDefault
->DefaultId
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
1408 CopyMem (&CurrentDefault
->Value
.Value
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1409 ExtendValueToU64 (&CurrentDefault
->Value
);
1412 // Insert to Default Value list of current Question
1414 InsertTailList (&CurrentStatement
->DefaultListHead
, &CurrentDefault
->Link
);
1417 InScopeDefault
= TRUE
;
1424 case EFI_IFR_ONE_OF_OPTION_OP
:
1426 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1427 // It create a selection for use in current Question.
1429 CurrentOption
= AllocateZeroPool (sizeof (QUESTION_OPTION
));
1430 ASSERT (CurrentOption
!= NULL
);
1431 CurrentOption
->Signature
= QUESTION_OPTION_SIGNATURE
;
1433 CurrentOption
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Flags
;
1434 CurrentOption
->Value
.Type
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Type
;
1435 CopyMem (&CurrentOption
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Option
, sizeof (EFI_STRING_ID
));
1436 CopyMem (&CurrentOption
->Value
.Value
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1437 ExtendValueToU64 (&CurrentOption
->Value
);
1439 if (InScopeOptionSuppress
) {
1440 CurrentOption
->SuppressExpression
= OptionSuppressExpression
;
1444 // Insert to Option list of current Question
1446 InsertTailList (&CurrentStatement
->OptionListHead
, &CurrentOption
->Link
);
1452 case EFI_IFR_NO_SUBMIT_IF_OP
:
1453 case EFI_IFR_INCONSISTENT_IF_OP
:
1455 // Create an Expression node
1457 CurrentExpression
= CreateExpression (CurrentForm
);
1458 CopyMem (&CurrentExpression
->Error
, &((EFI_IFR_INCONSISTENT_IF
*) OpCodeData
)->Error
, sizeof (EFI_STRING_ID
));
1460 if (Operand
== EFI_IFR_NO_SUBMIT_IF_OP
) {
1461 CurrentExpression
->Type
= EFI_HII_EXPRESSION_NO_SUBMIT_IF
;
1462 InsertTailList (&CurrentStatement
->NoSubmitListHead
, &CurrentExpression
->Link
);
1464 CurrentExpression
->Type
= EFI_HII_EXPRESSION_INCONSISTENT_IF
;
1465 InsertTailList (&CurrentStatement
->InconsistentListHead
, &CurrentExpression
->Link
);
1469 case EFI_IFR_SUPPRESS_IF_OP
:
1471 // Question and Option will appear in scope of this OpCode
1473 CurrentExpression
= CreateExpression (CurrentForm
);
1474 CurrentExpression
->Type
= EFI_HII_EXPRESSION_SUPPRESS_IF
;
1475 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1477 if (SuppressForOption
) {
1478 InScopeOptionSuppress
= TRUE
;
1479 OptionSuppressExpression
= CurrentExpression
;
1481 mInScopeSuppress
= TRUE
;
1482 mSuppressExpression
= CurrentExpression
;
1486 case EFI_IFR_GRAY_OUT_IF_OP
:
1488 // Questions will appear in scope of this OpCode
1490 CurrentExpression
= CreateExpression (CurrentForm
);
1491 CurrentExpression
->Type
= EFI_HII_EXPRESSION_GRAY_OUT_IF
;
1492 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1494 mInScopeGrayOut
= TRUE
;
1495 mGrayOutExpression
= CurrentExpression
;
1498 case EFI_IFR_DISABLE_IF_OP
:
1500 // The DisableIf expression should only rely on constant, so it could be
1501 // evaluated at initialization and it will not be queued
1503 CurrentExpression
= AllocateZeroPool (sizeof (FORM_EXPRESSION
));
1504 ASSERT (CurrentExpression
!= NULL
);
1505 CurrentExpression
->Signature
= FORM_EXPRESSION_SIGNATURE
;
1506 CurrentExpression
->Type
= EFI_HII_EXPRESSION_DISABLE_IF
;
1507 InitializeListHead (&CurrentExpression
->OpCodeListHead
);
1509 InScopeDisable
= TRUE
;
1510 OpCodeDisabled
= FALSE
;
1513 // Take a look at next OpCode to see whether current expression consists
1516 if (((EFI_IFR_OP_HEADER
*) (OpCodeData
+ OpCodeLength
))->Scope
== 0) {
1517 SingleOpCodeExpression
= TRUE
;
1524 case EFI_IFR_VALUE_OP
:
1525 CurrentExpression
= CreateExpression (CurrentForm
);
1526 CurrentExpression
->Type
= EFI_HII_EXPRESSION_VALUE
;
1527 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1529 if (InScopeDefault
) {
1531 // Used for default (EFI_IFR_DEFAULT)
1533 CurrentDefault
->ValueExpression
= CurrentExpression
;
1536 // If used for a question, then the question will be read-only
1539 // Make sure CurrentStatement is not NULL.
1540 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1541 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
1543 ASSERT (CurrentStatement
!= NULL
);
1544 CurrentStatement
->ValueExpression
= CurrentExpression
;
1548 case EFI_IFR_RULE_OP
:
1549 CurrentExpression
= CreateExpression (CurrentForm
);
1550 CurrentExpression
->Type
= EFI_HII_EXPRESSION_RULE
;
1552 CurrentExpression
->RuleId
= ((EFI_IFR_RULE
*) OpCodeData
)->RuleId
;
1553 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1559 case EFI_IFR_IMAGE_OP
:
1561 // Get ScopeOpcode from top of stack
1563 PopScope (&ScopeOpCode
);
1564 PushScope (ScopeOpCode
);
1566 switch (ScopeOpCode
) {
1567 case EFI_IFR_FORM_SET_OP
:
1568 ImageId
= &FormSet
->ImageId
;
1571 case EFI_IFR_FORM_OP
:
1572 ASSERT (CurrentForm
!= NULL
);
1573 ImageId
= &CurrentForm
->ImageId
;
1576 case EFI_IFR_ONE_OF_OPTION_OP
:
1577 ImageId
= &CurrentOption
->ImageId
;
1582 // Make sure CurrentStatement is not NULL.
1583 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1584 // file is wrongly generated by tools such as VFR Compiler.
1586 ASSERT (CurrentStatement
!= NULL
);
1587 ImageId
= &CurrentStatement
->ImageId
;
1591 ASSERT (ImageId
!= NULL
);
1592 CopyMem (ImageId
, &((EFI_IFR_IMAGE
*) OpCodeData
)->Id
, sizeof (EFI_IMAGE_ID
));
1598 case EFI_IFR_REFRESH_OP
:
1599 ASSERT (CurrentStatement
!= NULL
);
1600 CurrentStatement
->RefreshInterval
= ((EFI_IFR_REFRESH
*) OpCodeData
)->RefreshInterval
;
1606 case EFI_IFR_GUID_OP
:
1607 if (CompareGuid (&gEfiIfrTianoGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
1609 // Tiano specific GUIDed opcodes
1611 switch (((EFI_IFR_GUID_LABEL
*) OpCodeData
)->ExtendOpCode
) {
1612 case EFI_IFR_EXTEND_OP_LABEL
:
1614 // just ignore label
1618 case EFI_IFR_EXTEND_OP_BANNER
:
1619 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
1621 &BannerData
->Banner
[((EFI_IFR_GUID_BANNER
*) OpCodeData
)->LineNumber
][
1622 ((EFI_IFR_GUID_BANNER
*) OpCodeData
)->Alignment
],
1623 &((EFI_IFR_GUID_BANNER
*) OpCodeData
)->Title
,
1624 sizeof (EFI_STRING_ID
)
1629 case EFI_IFR_EXTEND_OP_CLASS
:
1630 CopyMem (&FormSet
->Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
1633 case EFI_IFR_EXTEND_OP_SUBCLASS
:
1634 CopyMem (&FormSet
->SubClass
, &((EFI_IFR_GUID_SUBCLASS
*) OpCodeData
)->SubClass
, sizeof (UINT16
));
1647 case EFI_IFR_END_OP
:
1648 Status
= PopScope (&ScopeOpCode
);
1649 if (EFI_ERROR (Status
)) {
1654 switch (ScopeOpCode
) {
1655 case EFI_IFR_FORM_SET_OP
:
1657 // End of FormSet, update FormSet IFR binary length
1658 // to stop parsing substantial OpCodes
1660 FormSet
->IfrBinaryLength
= OpCodeOffset
;
1663 case EFI_IFR_FORM_OP
:
1670 case EFI_IFR_ONE_OF_OPTION_OP
:
1674 CurrentOption
= NULL
;
1677 case EFI_IFR_SUBTITLE_OP
:
1678 mInScopeSubtitle
= FALSE
;
1681 case EFI_IFR_NO_SUBMIT_IF_OP
:
1682 case EFI_IFR_INCONSISTENT_IF_OP
:
1684 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1688 case EFI_IFR_SUPPRESS_IF_OP
:
1689 if (SuppressForOption
) {
1690 InScopeOptionSuppress
= FALSE
;
1692 mInScopeSuppress
= FALSE
;
1696 case EFI_IFR_GRAY_OUT_IF_OP
:
1697 mInScopeGrayOut
= FALSE
;
1700 case EFI_IFR_DISABLE_IF_OP
:
1701 InScopeDisable
= FALSE
;
1702 OpCodeDisabled
= FALSE
;
1705 case EFI_IFR_ONE_OF_OP
:
1706 case EFI_IFR_ORDERED_LIST_OP
:
1707 SuppressForOption
= FALSE
;
1710 case EFI_IFR_DEFAULT_OP
:
1711 InScopeDefault
= FALSE
;
1715 if (IsExpressionOpCode (ScopeOpCode
)) {
1716 if (InScopeDisable
) {
1718 // Evaluate DisableIf expression
1720 Status
= EvaluateExpression (FormSet
, CurrentForm
, CurrentExpression
);
1721 if (EFI_ERROR (Status
)) {
1725 ASSERT (CurrentExpression
!= NULL
);
1726 if (CurrentExpression
->Result
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1727 return EFI_INVALID_PARAMETER
;
1730 OpCodeDisabled
= CurrentExpression
->Result
.Value
.b
;
1732 // DisableIf Expression is only used once and not quequed, free it
1734 DestroyExpression (CurrentExpression
);
1738 // End of current Expression
1740 CurrentExpression
= NULL
;