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 BOOLEAN mInScopeDisable
;
25 FORM_EXPRESSION
*mSuppressExpression
;
26 FORM_EXPRESSION
*mGrayOutExpression
;
27 FORM_EXPRESSION
*mDisableExpression
;
30 Initialize Statement header members.
32 @param OpCodeData Pointer of the raw OpCode data.
33 @param FormSet Pointer of the current FormSe.
34 @param Form Pointer of the current Form.
36 @return The Statement.
39 FORM_BROWSER_STATEMENT
*
42 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
43 IN OUT FORM_BROWSER_FORM
*Form
46 FORM_BROWSER_STATEMENT
*Statement
;
47 EFI_IFR_STATEMENT_HEADER
*StatementHdr
;
51 // We are currently not in a Form Scope, so just skip this Statement
56 Statement
= &FormSet
->StatementBuffer
[mStatementIndex
];
59 InitializeListHead (&Statement
->DefaultListHead
);
60 InitializeListHead (&Statement
->OptionListHead
);
61 InitializeListHead (&Statement
->InconsistentListHead
);
62 InitializeListHead (&Statement
->NoSubmitListHead
);
64 Statement
->Signature
= FORM_BROWSER_STATEMENT_SIGNATURE
;
66 Statement
->Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
68 StatementHdr
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
69 CopyMem (&Statement
->Prompt
, &StatementHdr
->Prompt
, sizeof (EFI_STRING_ID
));
70 CopyMem (&Statement
->Help
, &StatementHdr
->Help
, sizeof (EFI_STRING_ID
));
72 if (mInScopeSuppress
) {
73 Statement
->SuppressExpression
= mSuppressExpression
;
76 if (mInScopeGrayOut
) {
77 Statement
->GrayOutExpression
= mGrayOutExpression
;
81 if (mInScopeDisable
) {
82 Statement
->DisableExpression
= mDisableExpression
;
85 Statement
->InSubtitle
= mInScopeSubtitle
;
88 // Insert this Statement into current Form
90 InsertTailList (&Form
->StatementListHead
, &Statement
->Link
);
96 Convert a numeric value to a Unicode String and insert it to String Package.
97 This string is used as the Unicode Name for the EFI Variable. This is to support
98 the deprecated vareqval opcode.
100 @param FormSet The FormSet.
101 @param Statement The numeric question whose VarStoreInfo.VarName is the
102 numeric value which is used to produce the Unicode Name
103 for the EFI Variable.
105 If the Statement is NULL, the ASSERT.
106 If the opcode is not Numeric, then ASSERT.
108 @retval EFI_SUCCESS The funtion always succeeds.
111 UpdateCheckBoxStringToken (
112 IN CONST FORM_BROWSER_FORMSET
*FormSet
,
113 IN FORM_BROWSER_STATEMENT
*Statement
116 CHAR16 Str
[MAXIMUM_VALUE_CHARACTERS
];
119 ASSERT (Statement
!= NULL
);
120 ASSERT (Statement
->Operand
== EFI_IFR_NUMERIC_OP
);
122 UnicodeValueToString (Str
, 0, Statement
->VarStoreInfo
.VarName
, MAXIMUM_VALUE_CHARACTERS
- 1);
124 Id
= HiiSetString (FormSet
->HiiHandle
, 0, Str
, NULL
);
126 return EFI_OUT_OF_RESOURCES
;
129 Statement
->VarStoreInfo
.VarName
= Id
;
135 Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.
137 @param OpCodeData The current opcode.
143 IsNextOpCodeGuidedVarEqName (
150 OpCodeData
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
151 if (*OpCodeData
== EFI_IFR_GUID_OP
) {
152 if (CompareGuid (&gEfiIfrFrameworkGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
154 // Specific GUIDed opcodes to support IFR generated from Framework HII VFR
156 if ((((EFI_IFR_GUID_VAREQNAME
*) OpCodeData
)->ExtendOpCode
) == EFI_IFR_EXTEND_OP_VAREQNAME
) {
166 Initialize Question's members.
168 @param OpCodeData Pointer of the raw OpCode data.
169 @param FormSet Pointer of the current FormSet.
170 @param Form Pointer of the current Form.
172 @return The Question.
175 FORM_BROWSER_STATEMENT
*
177 IN UINT8
*OpCodeData
,
178 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
179 IN OUT FORM_BROWSER_FORM
*Form
182 FORM_BROWSER_STATEMENT
*Statement
;
183 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
185 FORMSET_STORAGE
*Storage
;
186 NAME_VALUE_NODE
*NameValueNode
;
189 Statement
= CreateStatement (OpCodeData
, FormSet
, Form
);
190 if (Statement
== NULL
) {
194 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
195 CopyMem (&Statement
->QuestionId
, &QuestionHdr
->QuestionId
, sizeof (EFI_QUESTION_ID
));
196 CopyMem (&Statement
->VarStoreId
, &QuestionHdr
->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
197 CopyMem (&Statement
->VarStoreInfo
.VarOffset
, &QuestionHdr
->VarStoreInfo
.VarOffset
, sizeof (UINT16
));
199 Statement
->QuestionFlags
= QuestionHdr
->Flags
;
201 if (Statement
->VarStoreId
== 0) {
203 // VarStoreId of zero indicates no variable storage
209 // Take a look at next OpCode to see whether it is a GUIDed opcode to support
210 // Framework Compatibility
212 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
213 if ((*OpCodeData
== EFI_IFR_NUMERIC_OP
) && IsNextOpCodeGuidedVarEqName (OpCodeData
)) {
214 Status
= UpdateCheckBoxStringToken (FormSet
, Statement
);
215 if (EFI_ERROR (Status
)) {
222 // Find Storage for this Question
224 Link
= GetFirstNode (&FormSet
->StorageListHead
);
225 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
226 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
228 if (Storage
->VarStoreId
== Statement
->VarStoreId
) {
229 Statement
->Storage
= Storage
;
233 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
235 ASSERT (Statement
->Storage
!= NULL
);
238 // Initialilze varname for Name/Value or EFI Variable
240 if ((Statement
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) ||
241 (Statement
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
242 Statement
->VariableName
= GetToken (Statement
->VarStoreInfo
.VarName
, FormSet
->HiiHandle
);
243 ASSERT (Statement
->VariableName
!= NULL
);
245 if (Statement
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
247 // Insert to Name/Value varstore list
249 NameValueNode
= AllocateZeroPool (sizeof (NAME_VALUE_NODE
));
250 ASSERT (NameValueNode
!= NULL
);
251 NameValueNode
->Signature
= NAME_VALUE_NODE_SIGNATURE
;
252 NameValueNode
->Name
= AllocateCopyPool (StrSize (Statement
->VariableName
), Statement
->VariableName
);
253 ASSERT (NameValueNode
->Name
!= NULL
);
254 NameValueNode
->Value
= AllocateZeroPool (0x10);
255 ASSERT (NameValueNode
->Value
!= NULL
);
256 NameValueNode
->EditValue
= AllocateZeroPool (0x10);
257 ASSERT (NameValueNode
->EditValue
!= NULL
);
259 InsertTailList (&Statement
->Storage
->NameValueListHead
, &NameValueNode
->Link
);
268 Allocate a FORM_EXPRESSION node.
270 @param Form The Form associated with this Expression
272 @return Pointer to a FORM_EXPRESSION data structure.
277 IN OUT FORM_BROWSER_FORM
*Form
280 FORM_EXPRESSION
*Expression
;
282 Expression
= AllocateZeroPool (sizeof (FORM_EXPRESSION
));
283 ASSERT (Expression
!= NULL
);
284 Expression
->Signature
= FORM_EXPRESSION_SIGNATURE
;
285 InitializeListHead (&Expression
->OpCodeListHead
);
292 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
294 @param FormSet Pointer of the current FormSet
296 @return Pointer to a FORMSET_STORAGE data structure.
301 IN FORM_BROWSER_FORMSET
*FormSet
304 FORMSET_STORAGE
*Storage
;
306 Storage
= AllocateZeroPool (sizeof (FORMSET_STORAGE
));
307 ASSERT (Storage
!= NULL
);
308 Storage
->Signature
= FORMSET_STORAGE_SIGNATURE
;
309 InitializeListHead (&Storage
->NameValueListHead
);
310 InsertTailList (&FormSet
->StorageListHead
, &Storage
->Link
);
317 Create ConfigHdr string for a storage.
319 @param FormSet Pointer of the current FormSet
320 @param Storage Pointer of the storage
322 @retval EFI_SUCCESS Initialize ConfigHdr success
326 InitializeConfigHdr (
327 IN FORM_BROWSER_FORMSET
*FormSet
,
328 IN OUT FORMSET_STORAGE
*Storage
333 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
334 Name
= Storage
->Name
;
339 Storage
->ConfigHdr
= HiiConstructConfigHdr (
342 FormSet
->DriverHandle
345 if (Storage
->ConfigHdr
== NULL
) {
346 return EFI_NOT_FOUND
;
349 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigHdr
), Storage
->ConfigHdr
);
350 Storage
->SpareStrLen
= 0;
357 Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
359 @param FormSet Pointer of the current FormSet.
360 @param Question The Question to be initialized.
362 @retval EFI_SUCCESS Function success.
363 @retval EFI_INVALID_PARAMETER No storage associated with the Question.
367 InitializeRequestElement (
368 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
369 IN OUT FORM_BROWSER_STATEMENT
*Question
372 FORMSET_STORAGE
*Storage
;
376 CHAR16 RequestElement
[30];
378 Storage
= Question
->Storage
;
379 if (Storage
== NULL
) {
380 return EFI_INVALID_PARAMETER
;
383 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
385 // <ConfigRequest> is unnecessary for EFI variable storage,
386 // GetVariable()/SetVariable() will be used to retrieve/save values
392 // Prepare <RequestElement>
394 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
395 StrLen
= UnicodeSPrint (
397 30 * sizeof (CHAR16
),
398 L
"&OFFSET=%x&WIDTH=%x",
399 Question
->VarStoreInfo
.VarOffset
,
400 Question
->StorageWidth
402 Question
->BlockName
= AllocateCopyPool ((StrLen
+ 1) * sizeof (CHAR16
), RequestElement
);
404 StrLen
= UnicodeSPrint (RequestElement
, 30 * sizeof (CHAR16
), L
"&%s", Question
->VariableName
);
407 if ((Question
->Operand
== EFI_IFR_PASSWORD_OP
) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
409 // Password with CALLBACK flag is stored in encoded format,
410 // so don't need to append it to <ConfigRequest>
416 // Append <RequestElement> to <ConfigRequest>
418 if (StrLen
> Storage
->SpareStrLen
) {
420 // Old String buffer is not sufficient for RequestElement, allocate a new one
422 StringSize
= (Storage
->ConfigRequest
!= NULL
) ? StrSize (Storage
->ConfigRequest
) : sizeof (CHAR16
);
423 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
424 ASSERT (NewStr
!= NULL
);
425 if (Storage
->ConfigRequest
!= NULL
) {
426 CopyMem (NewStr
, Storage
->ConfigRequest
, StringSize
);
427 FreePool (Storage
->ConfigRequest
);
429 Storage
->ConfigRequest
= NewStr
;
430 Storage
->SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
433 StrCat (Storage
->ConfigRequest
, RequestElement
);
434 Storage
->ElementCount
++;
435 Storage
->SpareStrLen
-= StrLen
;
442 Free resources of a Expression.
444 @param FormSet Pointer of the Expression
449 IN FORM_EXPRESSION
*Expression
453 EXPRESSION_OPCODE
*OpCode
;
455 while (!IsListEmpty (&Expression
->OpCodeListHead
)) {
456 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
457 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
458 RemoveEntryList (&OpCode
->Link
);
460 if (OpCode
->ValueList
!= NULL
) {
461 FreePool (OpCode
->ValueList
);
466 // Free this Expression
468 FreePool (Expression
);
473 Free resources of a storage.
475 @param Storage Pointer of the storage
480 IN FORMSET_STORAGE
*Storage
484 NAME_VALUE_NODE
*NameValueNode
;
486 if (Storage
== NULL
) {
490 if (Storage
->Name
!= NULL
) {
491 FreePool (Storage
->Name
);
493 if (Storage
->Buffer
!= NULL
) {
494 FreePool (Storage
->Buffer
);
496 if (Storage
->EditBuffer
!= NULL
) {
497 FreePool (Storage
->EditBuffer
);
500 while (!IsListEmpty (&Storage
->NameValueListHead
)) {
501 Link
= GetFirstNode (&Storage
->NameValueListHead
);
502 NameValueNode
= NAME_VALUE_NODE_FROM_LINK (Link
);
503 RemoveEntryList (&NameValueNode
->Link
);
505 if (NameValueNode
->Name
!= NULL
) {
506 FreePool (NameValueNode
->Name
);
508 if (NameValueNode
->Value
!= NULL
) {
509 FreePool (NameValueNode
->Value
);
511 if (NameValueNode
->EditValue
!= NULL
) {
512 FreePool (NameValueNode
->EditValue
);
514 FreePool (NameValueNode
);
517 if (Storage
->ConfigHdr
!= NULL
) {
518 FreePool (Storage
->ConfigHdr
);
520 if (Storage
->ConfigRequest
!= NULL
) {
521 FreePool (Storage
->ConfigRequest
);
529 Free resources of a Statement.
531 @param Statement Pointer of the Statement
536 IN OUT FORM_BROWSER_STATEMENT
*Statement
540 QUESTION_DEFAULT
*Default
;
541 QUESTION_OPTION
*Option
;
542 FORM_EXPRESSION
*Expression
;
545 // Free Default value List
547 while (!IsListEmpty (&Statement
->DefaultListHead
)) {
548 Link
= GetFirstNode (&Statement
->DefaultListHead
);
549 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
550 RemoveEntryList (&Default
->Link
);
558 while (!IsListEmpty (&Statement
->OptionListHead
)) {
559 Link
= GetFirstNode (&Statement
->OptionListHead
);
560 Option
= QUESTION_OPTION_FROM_LINK (Link
);
561 RemoveEntryList (&Option
->Link
);
567 // Free Inconsistent List
569 while (!IsListEmpty (&Statement
->InconsistentListHead
)) {
570 Link
= GetFirstNode (&Statement
->InconsistentListHead
);
571 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
572 RemoveEntryList (&Expression
->Link
);
574 DestroyExpression (Expression
);
578 // Free NoSubmit List
580 while (!IsListEmpty (&Statement
->NoSubmitListHead
)) {
581 Link
= GetFirstNode (&Statement
->NoSubmitListHead
);
582 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
583 RemoveEntryList (&Expression
->Link
);
585 DestroyExpression (Expression
);
588 if (Statement
->VariableName
!= NULL
) {
589 FreePool (Statement
->VariableName
);
591 if (Statement
->BlockName
!= NULL
) {
592 FreePool (Statement
->BlockName
);
598 Free resources of a Form.
600 @param Form Pointer of the Form.
605 IN OUT FORM_BROWSER_FORM
*Form
609 FORM_EXPRESSION
*Expression
;
610 FORM_BROWSER_STATEMENT
*Statement
;
613 // Free Form Expressions
615 while (!IsListEmpty (&Form
->ExpressionListHead
)) {
616 Link
= GetFirstNode (&Form
->ExpressionListHead
);
617 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
618 RemoveEntryList (&Expression
->Link
);
620 DestroyExpression (Expression
);
624 // Free Statements/Questions
626 while (!IsListEmpty (&Form
->StatementListHead
)) {
627 Link
= GetFirstNode (&Form
->StatementListHead
);
628 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
629 RemoveEntryList (&Statement
->Link
);
631 DestroyStatement (Statement
);
642 Free resources allocated for a FormSet.
644 @param FormSet Pointer of the FormSet
649 IN OUT FORM_BROWSER_FORMSET
*FormSet
653 FORMSET_STORAGE
*Storage
;
654 FORMSET_DEFAULTSTORE
*DefaultStore
;
655 FORM_BROWSER_FORM
*Form
;
658 // Free IFR binary buffer
660 FreePool (FormSet
->IfrBinaryData
);
663 // Free FormSet Storage
665 if (FormSet
->StorageListHead
.ForwardLink
!= NULL
) {
666 while (!IsListEmpty (&FormSet
->StorageListHead
)) {
667 Link
= GetFirstNode (&FormSet
->StorageListHead
);
668 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
669 RemoveEntryList (&Storage
->Link
);
671 DestroyStorage (Storage
);
676 // Free FormSet Default Store
678 if (FormSet
->DefaultStoreListHead
.ForwardLink
!= NULL
) {
679 while (!IsListEmpty (&FormSet
->DefaultStoreListHead
)) {
680 Link
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
681 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (Link
);
682 RemoveEntryList (&DefaultStore
->Link
);
684 FreePool (DefaultStore
);
691 if (FormSet
->FormListHead
.ForwardLink
!= NULL
) {
692 while (!IsListEmpty (&FormSet
->FormListHead
)) {
693 Link
= GetFirstNode (&FormSet
->FormListHead
);
694 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
695 RemoveEntryList (&Form
->Link
);
701 if (FormSet
->StatementBuffer
!= NULL
) {
702 FreePool (FormSet
->StatementBuffer
);
704 if (FormSet
->ExpressionBuffer
!= NULL
) {
705 FreePool (FormSet
->ExpressionBuffer
);
713 Tell whether this Operand is an Expression OpCode or not
715 @param Operand Operand of an IFR OpCode.
717 @retval TRUE This is an Expression OpCode.
718 @retval FALSE Not an Expression OpCode.
726 if (((Operand
>= EFI_IFR_EQ_ID_VAL_OP
) && (Operand
<= EFI_IFR_NOT_OP
)) ||
727 ((Operand
>= EFI_IFR_MATCH_OP
) && (Operand
<= EFI_IFR_SPAN_OP
)) ||
728 (Operand
== EFI_IFR_CATENATE_OP
) ||
729 (Operand
== EFI_IFR_TO_LOWER_OP
) ||
730 (Operand
== EFI_IFR_TO_UPPER_OP
) ||
731 (Operand
== EFI_IFR_VERSION_OP
)
741 Calculate number of Statemens(Questions) and Expression OpCodes.
743 @param FormSet The FormSet to be counted.
744 @param NumberOfStatement Number of Statemens(Questions)
745 @param NumberOfExpression Number of Expression OpCodes
750 IN FORM_BROWSER_FORMSET
*FormSet
,
751 IN OUT UINT16
*NumberOfStatement
,
752 IN OUT UINT16
*NumberOfExpression
755 UINT16 StatementCount
;
756 UINT16 ExpressionCount
;
765 while (Offset
< FormSet
->IfrBinaryLength
) {
766 OpCodeData
= FormSet
->IfrBinaryData
+ Offset
;
767 OpCodeLen
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
770 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
)) {
777 *NumberOfStatement
= StatementCount
;
778 *NumberOfExpression
= ExpressionCount
;
784 Parse opcodes in the formset IFR binary.
786 @param FormSet Pointer of the FormSet data structure.
788 @retval EFI_SUCCESS Opcode parse success.
789 @retval Other Opcode parse fail.
794 IN FORM_BROWSER_FORMSET
*FormSet
799 FORM_BROWSER_FORM
*CurrentForm
;
800 FORM_BROWSER_STATEMENT
*CurrentStatement
;
801 EXPRESSION_OPCODE
*ExpressionOpCode
;
802 FORM_EXPRESSION
*CurrentExpression
;
809 FORMSET_STORAGE
*Storage
;
810 FORMSET_DEFAULTSTORE
*DefaultStore
;
811 QUESTION_DEFAULT
*CurrentDefault
;
812 QUESTION_OPTION
*CurrentOption
;
814 UINT16 NumberOfStatement
;
815 UINT16 NumberOfExpression
;
816 EFI_IMAGE_ID
*ImageId
;
817 BOOLEAN SuppressForOption
;
818 BOOLEAN InScopeOptionSuppress
;
819 FORM_EXPRESSION
*OptionSuppressExpression
;
820 UINT16 DepthOfDisable
;
821 BOOLEAN OpCodeDisabled
;
822 BOOLEAN SingleOpCodeExpression
;
823 BOOLEAN InScopeDefault
;
824 EFI_HII_VALUE
*Value
;
826 mInScopeSubtitle
= FALSE
;
827 SuppressForOption
= FALSE
;
828 mInScopeSuppress
= FALSE
;
829 InScopeOptionSuppress
= FALSE
;
830 mInScopeGrayOut
= FALSE
;
831 mInScopeDisable
= FALSE
;
833 OpCodeDisabled
= FALSE
;
834 SingleOpCodeExpression
= FALSE
;
835 InScopeDefault
= FALSE
;
836 CurrentExpression
= NULL
;
837 CurrentDefault
= NULL
;
838 CurrentOption
= NULL
;
839 OptionSuppressExpression
= NULL
;
843 // Get the number of Statements and Expressions
845 CountOpCodes (FormSet
, &NumberOfStatement
, &NumberOfExpression
);
848 FormSet
->StatementBuffer
= AllocateZeroPool (NumberOfStatement
* sizeof (FORM_BROWSER_STATEMENT
));
849 if (FormSet
->StatementBuffer
== NULL
) {
850 return EFI_OUT_OF_RESOURCES
;
853 mExpressionOpCodeIndex
= 0;
854 FormSet
->ExpressionBuffer
= AllocateZeroPool (NumberOfExpression
* sizeof (EXPRESSION_OPCODE
));
855 if (FormSet
->ExpressionBuffer
== NULL
) {
856 return EFI_OUT_OF_RESOURCES
;
859 InitializeListHead (&FormSet
->StorageListHead
);
860 InitializeListHead (&FormSet
->DefaultStoreListHead
);
861 InitializeListHead (&FormSet
->FormListHead
);
864 CurrentStatement
= NULL
;
869 while (OpCodeOffset
< FormSet
->IfrBinaryLength
) {
870 OpCodeData
= FormSet
->IfrBinaryData
+ OpCodeOffset
;
872 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
873 OpCodeOffset
+= OpCodeLength
;
874 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
875 Scope
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Scope
;
878 // If scope bit set, push onto scope stack
884 if (OpCodeDisabled
) {
886 // DisableIf Expression is evaluated to be TRUE, try to find its end.
887 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
889 if (Operand
== EFI_IFR_DISABLE_IF_OP
) {
891 } else if (Operand
== EFI_IFR_END_OP
) {
892 Status
= PopScope (&ScopeOpCode
);
893 if (EFI_ERROR (Status
)) {
897 if (ScopeOpCode
== EFI_IFR_DISABLE_IF_OP
) {
898 if (DepthOfDisable
== 0) {
899 mInScopeDisable
= FALSE
;
900 OpCodeDisabled
= FALSE
;
909 if (IsExpressionOpCode (Operand
)) {
910 ExpressionOpCode
= &FormSet
->ExpressionBuffer
[mExpressionOpCodeIndex
];
911 mExpressionOpCodeIndex
++;
913 ExpressionOpCode
->Signature
= EXPRESSION_OPCODE_SIGNATURE
;
914 ExpressionOpCode
->Operand
= Operand
;
915 Value
= &ExpressionOpCode
->Value
;
918 case EFI_IFR_EQ_ID_VAL_OP
:
919 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_VAL
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
921 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
922 CopyMem (&Value
->Value
.u16
, &((EFI_IFR_EQ_ID_VAL
*) OpCodeData
)->Value
, sizeof (UINT16
));
925 case EFI_IFR_EQ_ID_ID_OP
:
926 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_ID
*) OpCodeData
)->QuestionId1
, sizeof (EFI_QUESTION_ID
));
927 CopyMem (&ExpressionOpCode
->QuestionId2
, &((EFI_IFR_EQ_ID_ID
*) OpCodeData
)->QuestionId2
, sizeof (EFI_QUESTION_ID
));
930 case EFI_IFR_EQ_ID_LIST_OP
:
931 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_VAL_LIST
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
932 CopyMem (&ExpressionOpCode
->ListLength
, &((EFI_IFR_EQ_ID_VAL_LIST
*) OpCodeData
)->ListLength
, sizeof (UINT16
));
933 ExpressionOpCode
->ValueList
= AllocateCopyPool (ExpressionOpCode
->ListLength
* sizeof (UINT16
), &((EFI_IFR_EQ_ID_VAL_LIST
*) OpCodeData
)->ValueList
);
936 case EFI_IFR_TO_STRING_OP
:
937 case EFI_IFR_FIND_OP
:
938 ExpressionOpCode
->Format
= (( EFI_IFR_TO_STRING
*) OpCodeData
)->Format
;
941 case EFI_IFR_STRING_REF1_OP
:
942 Value
->Type
= EFI_IFR_TYPE_STRING
;
943 CopyMem (&Value
->Value
.string
, &(( EFI_IFR_STRING_REF1
*) OpCodeData
)->StringId
, sizeof (EFI_STRING_ID
));
946 case EFI_IFR_RULE_REF_OP
:
947 ExpressionOpCode
->RuleId
= (( EFI_IFR_RULE_REF
*) OpCodeData
)->RuleId
;
950 case EFI_IFR_SPAN_OP
:
951 ExpressionOpCode
->Flags
= (( EFI_IFR_SPAN
*) OpCodeData
)->Flags
;
954 case EFI_IFR_THIS_OP
:
955 ASSERT (CurrentStatement
!= NULL
);
956 ExpressionOpCode
->QuestionId
= CurrentStatement
->QuestionId
;
959 case EFI_IFR_QUESTION_REF1_OP
:
960 CopyMem (&ExpressionOpCode
->QuestionId
, &((EFI_IFR_EQ_ID_VAL_LIST
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
963 case EFI_IFR_QUESTION_REF3_OP
:
964 if (OpCodeLength
>= sizeof (EFI_IFR_QUESTION_REF3_2
)) {
965 CopyMem (&ExpressionOpCode
->DevicePath
, &(( EFI_IFR_QUESTION_REF3_2
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
967 if (OpCodeLength
>= sizeof (EFI_IFR_QUESTION_REF3_3
)) {
968 CopyMem (&ExpressionOpCode
->Guid
, &(( EFI_IFR_QUESTION_REF3_3
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
976 case EFI_IFR_TRUE_OP
:
977 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
978 Value
->Value
.b
= TRUE
;
981 case EFI_IFR_FALSE_OP
:
982 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
983 Value
->Value
.b
= FALSE
;
987 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
991 case EFI_IFR_ZERO_OP
:
992 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
996 case EFI_IFR_ONES_OP
:
997 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
998 Value
->Value
.u64
= 0xffffffffffffffffULL
;
1001 case EFI_IFR_UINT8_OP
:
1002 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1003 Value
->Value
.u8
= (( EFI_IFR_UINT8
*) OpCodeData
)->Value
;
1006 case EFI_IFR_UINT16_OP
:
1007 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1008 CopyMem (&Value
->Value
.u16
, &(( EFI_IFR_UINT16
*) OpCodeData
)->Value
, sizeof (UINT16
));
1011 case EFI_IFR_UINT32_OP
:
1012 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
1013 CopyMem (&Value
->Value
.u32
, &(( EFI_IFR_UINT32
*) OpCodeData
)->Value
, sizeof (UINT32
));
1016 case EFI_IFR_UINT64_OP
:
1017 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1018 CopyMem (&Value
->Value
.u64
, &(( EFI_IFR_UINT64
*) OpCodeData
)->Value
, sizeof (UINT64
));
1021 case EFI_IFR_UNDEFINED_OP
:
1022 Value
->Type
= EFI_IFR_TYPE_OTHER
;
1025 case EFI_IFR_VERSION_OP
:
1026 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1027 Value
->Value
.u16
= EFI_IFR_SPECIFICATION_VERSION
;
1034 InsertTailList (&CurrentExpression
->OpCodeListHead
, &ExpressionOpCode
->Link
);
1036 if (SingleOpCodeExpression
) {
1038 // There are two cases to indicate the end of an Expression:
1039 // for single OpCode expression: one Expression OpCode
1040 // for expression consists of more than one OpCode: EFI_IFR_END
1042 SingleOpCodeExpression
= FALSE
;
1044 if (mInScopeDisable
&& CurrentForm
== NULL
) {
1046 // This is DisableIf expression for Form, it should be a constant expression
1048 Status
= EvaluateExpression (FormSet
, CurrentForm
, CurrentExpression
);
1049 if (EFI_ERROR (Status
)) {
1053 ASSERT (CurrentExpression
!= NULL
);
1054 if (CurrentExpression
->Result
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1055 return EFI_INVALID_PARAMETER
;
1058 OpCodeDisabled
= CurrentExpression
->Result
.Value
.b
;
1061 CurrentExpression
= NULL
;
1072 case EFI_IFR_FORM_SET_OP
:
1074 // check the formset GUID
1076 if (CompareMem (&FormSet
->Guid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
)) != 0) {
1077 return EFI_INVALID_PARAMETER
;
1080 CopyMem (&FormSet
->FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
1081 CopyMem (&FormSet
->Help
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
1084 // The formset OpCode contains ClassGuid
1086 FormSet
->NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
1087 CopyMem (FormSet
->ClassGuid
, OpCodeData
+ sizeof (EFI_IFR_FORM_SET
), FormSet
->NumberOfClassGuid
* sizeof (EFI_GUID
));
1090 case EFI_IFR_FORM_OP
:
1092 // Create a new Form for this FormSet
1094 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
1095 ASSERT (CurrentForm
!= NULL
);
1096 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
1097 InitializeListHead (&CurrentForm
->ExpressionListHead
);
1098 InitializeListHead (&CurrentForm
->StatementListHead
);
1100 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
1101 CopyMem (&CurrentForm
->FormTitle
, &((EFI_IFR_FORM
*) OpCodeData
)->FormTitle
, sizeof (EFI_STRING_ID
));
1104 // Insert into Form list of this FormSet
1106 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
1112 case EFI_IFR_VARSTORE_OP
:
1114 // Create a buffer Storage for this FormSet
1116 Storage
= CreateStorage (FormSet
);
1117 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
1119 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1120 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1121 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
1123 Storage
->Buffer
= AllocateZeroPool (Storage
->Size
);
1124 Storage
->EditBuffer
= AllocateZeroPool (Storage
->Size
);
1126 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
1127 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
1128 ASSERT (Storage
->Name
!= NULL
);
1129 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1130 Storage
->Name
[Index
] = (CHAR16
) AsciiString
[Index
];
1134 // Initialize <ConfigHdr>
1136 InitializeConfigHdr (FormSet
, Storage
);
1139 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1141 // Create a name/value Storage for this FormSet
1143 Storage
= CreateStorage (FormSet
);
1144 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1146 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1147 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1150 // Initialize <ConfigHdr>
1152 InitializeConfigHdr (FormSet
, Storage
);
1155 case EFI_IFR_VARSTORE_EFI_OP
:
1157 // Create a EFI variable Storage for this FormSet
1159 Storage
= CreateStorage (FormSet
);
1160 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
1162 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
1163 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
1164 CopyMem (&Storage
->Attributes
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Attributes
, sizeof (UINT32
));
1170 case EFI_IFR_DEFAULTSTORE_OP
:
1171 DefaultStore
= AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE
));
1172 ASSERT (DefaultStore
!= NULL
);
1173 DefaultStore
->Signature
= FORMSET_DEFAULTSTORE_SIGNATURE
;
1175 CopyMem (&DefaultStore
->DefaultId
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
1176 CopyMem (&DefaultStore
->DefaultName
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultName
, sizeof (EFI_STRING_ID
));
1179 // Insert to DefaultStore list of this Formset
1181 InsertTailList (&FormSet
->DefaultStoreListHead
, &DefaultStore
->Link
);
1187 case EFI_IFR_SUBTITLE_OP
:
1188 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
1189 ASSERT (CurrentStatement
!= NULL
);
1191 CurrentStatement
->Flags
= ((EFI_IFR_SUBTITLE
*) OpCodeData
)->Flags
;
1194 mInScopeSubtitle
= TRUE
;
1198 case EFI_IFR_TEXT_OP
:
1199 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
1200 ASSERT (CurrentStatement
!= NULL
);
1202 CopyMem (&CurrentStatement
->TextTwo
, &((EFI_IFR_TEXT
*) OpCodeData
)->TextTwo
, sizeof (EFI_STRING_ID
));
1208 case EFI_IFR_ACTION_OP
:
1209 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1210 ASSERT (CurrentStatement
!= NULL
);
1212 if (OpCodeLength
== sizeof (EFI_IFR_ACTION_1
)) {
1214 // No QuestionConfig present, so no configuration string will be processed
1216 CurrentStatement
->QuestionConfig
= 0;
1218 CopyMem (&CurrentStatement
->QuestionConfig
, &((EFI_IFR_ACTION
*) OpCodeData
)->QuestionConfig
, sizeof (EFI_STRING_ID
));
1222 case EFI_IFR_RESET_BUTTON_OP
:
1226 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
1227 ASSERT (CurrentStatement
!= NULL
);
1228 CopyMem (&CurrentStatement
->DefaultId
, &((EFI_IFR_RESET_BUTTON
*) OpCodeData
)->DefaultId
, sizeof (EFI_DEFAULT_ID
));
1231 case EFI_IFR_REF_OP
:
1232 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1233 ASSERT (CurrentStatement
!= NULL
);
1234 CopyMem (&CurrentStatement
->RefFormId
, &((EFI_IFR_REF
*) OpCodeData
)->FormId
, sizeof (EFI_FORM_ID
));
1235 if (OpCodeLength
>= sizeof (EFI_IFR_REF2
)) {
1236 CopyMem (&CurrentStatement
->RefQuestionId
, &((EFI_IFR_REF2
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
1238 if (OpCodeLength
>= sizeof (EFI_IFR_REF3
)) {
1239 CopyMem (&CurrentStatement
->RefFormSetId
, &((EFI_IFR_REF3
*) OpCodeData
)->FormSetId
, sizeof (EFI_GUID
));
1241 if (OpCodeLength
>= sizeof (EFI_IFR_REF4
)) {
1242 CopyMem (&CurrentStatement
->RefDevicePath
, &((EFI_IFR_REF4
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
1248 case EFI_IFR_ONE_OF_OP
:
1249 case EFI_IFR_NUMERIC_OP
:
1250 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1251 ASSERT(CurrentStatement
!= NULL
);
1253 CurrentStatement
->Flags
= ((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
;
1254 Value
= &CurrentStatement
->HiiValue
;
1256 switch (CurrentStatement
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1257 case EFI_IFR_NUMERIC_SIZE_1
:
1258 CurrentStatement
->Minimum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MinValue
;
1259 CurrentStatement
->Maximum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MaxValue
;
1260 CurrentStatement
->Step
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.Step
;
1261 CurrentStatement
->StorageWidth
= sizeof (UINT8
);
1262 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1265 case EFI_IFR_NUMERIC_SIZE_2
:
1266 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MinValue
, sizeof (UINT16
));
1267 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MaxValue
, sizeof (UINT16
));
1268 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.Step
, sizeof (UINT16
));
1269 CurrentStatement
->StorageWidth
= sizeof (UINT16
);
1270 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1273 case EFI_IFR_NUMERIC_SIZE_4
:
1274 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MinValue
, sizeof (UINT32
));
1275 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MaxValue
, sizeof (UINT32
));
1276 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.Step
, sizeof (UINT32
));
1277 CurrentStatement
->StorageWidth
= sizeof (UINT32
);
1278 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
1281 case EFI_IFR_NUMERIC_SIZE_8
:
1282 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MinValue
, sizeof (UINT64
));
1283 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MaxValue
, sizeof (UINT64
));
1284 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.Step
, sizeof (UINT64
));
1285 CurrentStatement
->StorageWidth
= sizeof (UINT64
);
1286 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1293 InitializeRequestElement (FormSet
, CurrentStatement
);
1295 if ((Operand
== EFI_IFR_ONE_OF_OP
) && Scope
!= 0) {
1296 SuppressForOption
= TRUE
;
1300 case EFI_IFR_ORDERED_LIST_OP
:
1301 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1302 ASSERT(CurrentStatement
!= NULL
);
1304 CurrentStatement
->Flags
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Flags
;
1305 CurrentStatement
->MaxContainers
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1306 CurrentStatement
->StorageWidth
= (UINT16
)(CurrentStatement
->MaxContainers
* sizeof (UINT8
));
1307 InitializeRequestElement (FormSet
, CurrentStatement
);
1310 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
1311 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
1312 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
1314 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_OTHER
;
1315 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
1318 SuppressForOption
= TRUE
;
1322 case EFI_IFR_CHECKBOX_OP
:
1323 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1324 ASSERT(CurrentStatement
!= NULL
);
1326 CurrentStatement
->Flags
= ((EFI_IFR_CHECKBOX
*) OpCodeData
)->Flags
;
1327 CurrentStatement
->StorageWidth
= sizeof (BOOLEAN
);
1328 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_BOOLEAN
;
1330 InitializeRequestElement (FormSet
, CurrentStatement
);
1334 case EFI_IFR_STRING_OP
:
1335 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1336 ASSERT (CurrentStatement
!= NULL
);
1338 // MinSize is the minimum number of characters that can be accepted for this opcode,
1339 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1340 // The characters are stored as Unicode, so the storage width should multiply 2.
1342 CurrentStatement
->Minimum
= ((EFI_IFR_STRING
*) OpCodeData
)->MinSize
;
1343 CurrentStatement
->Maximum
= ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
;
1344 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (CHAR16
));
1345 CurrentStatement
->Flags
= ((EFI_IFR_STRING
*) OpCodeData
)->Flags
;
1347 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
1348 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
+ sizeof (CHAR16
));
1350 InitializeRequestElement (FormSet
, CurrentStatement
);
1353 case EFI_IFR_PASSWORD_OP
:
1354 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1355 ASSERT (CurrentStatement
!= NULL
);
1357 // MinSize is the minimum number of characters that can be accepted for this opcode,
1358 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1359 // The characters are stored as Unicode, so the storage width should multiply 2.
1361 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MinSize
, sizeof (UINT16
));
1362 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
, sizeof (UINT16
));
1363 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (CHAR16
));
1365 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
1366 CurrentStatement
->BufferValue
= AllocateZeroPool ((CurrentStatement
->StorageWidth
+ sizeof (CHAR16
)));
1368 InitializeRequestElement (FormSet
, CurrentStatement
);
1371 case EFI_IFR_DATE_OP
:
1372 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1373 ASSERT(CurrentStatement
!= NULL
);
1375 CurrentStatement
->Flags
= ((EFI_IFR_DATE
*) OpCodeData
)->Flags
;
1376 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_DATE
;
1378 if ((CurrentStatement
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_NORMAL
) {
1379 CurrentStatement
->StorageWidth
= sizeof (EFI_HII_DATE
);
1381 InitializeRequestElement (FormSet
, CurrentStatement
);
1384 // Don't assign storage for RTC type of date/time
1386 CurrentStatement
->Storage
= NULL
;
1387 CurrentStatement
->StorageWidth
= 0;
1391 case EFI_IFR_TIME_OP
:
1392 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
1393 ASSERT(CurrentStatement
!= NULL
);
1395 CurrentStatement
->Flags
= ((EFI_IFR_TIME
*) OpCodeData
)->Flags
;
1396 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_TIME
;
1398 if ((CurrentStatement
->Flags
& QF_TIME_STORAGE
) == QF_TIME_STORAGE_NORMAL
) {
1399 CurrentStatement
->StorageWidth
= sizeof (EFI_IFR_TIME
);
1401 InitializeRequestElement (FormSet
, CurrentStatement
);
1404 // Don't assign storage for RTC type of date/time
1406 CurrentStatement
->Storage
= NULL
;
1407 CurrentStatement
->StorageWidth
= 0;
1414 case EFI_IFR_DEFAULT_OP
:
1416 // EFI_IFR_DEFAULT appear in scope of a Question,
1417 // It creates a default value for the current question.
1418 // A Question may have more than one Default value which have different default types.
1420 CurrentDefault
= AllocateZeroPool (sizeof (QUESTION_DEFAULT
));
1421 ASSERT (CurrentDefault
!= NULL
);
1422 CurrentDefault
->Signature
= QUESTION_DEFAULT_SIGNATURE
;
1424 CurrentDefault
->Value
.Type
= ((EFI_IFR_DEFAULT
*) OpCodeData
)->Type
;
1425 CopyMem (&CurrentDefault
->DefaultId
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
1426 CopyMem (&CurrentDefault
->Value
.Value
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1427 ExtendValueToU64 (&CurrentDefault
->Value
);
1430 // Insert to Default Value list of current Question
1432 InsertTailList (&CurrentStatement
->DefaultListHead
, &CurrentDefault
->Link
);
1435 InScopeDefault
= TRUE
;
1442 case EFI_IFR_ONE_OF_OPTION_OP
:
1444 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1445 // It create a selection for use in current Question.
1447 CurrentOption
= AllocateZeroPool (sizeof (QUESTION_OPTION
));
1448 ASSERT (CurrentOption
!= NULL
);
1449 CurrentOption
->Signature
= QUESTION_OPTION_SIGNATURE
;
1451 CurrentOption
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Flags
;
1452 CurrentOption
->Value
.Type
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Type
;
1453 CopyMem (&CurrentOption
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Option
, sizeof (EFI_STRING_ID
));
1454 CopyMem (&CurrentOption
->Value
.Value
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1455 ExtendValueToU64 (&CurrentOption
->Value
);
1457 if (InScopeOptionSuppress
) {
1458 CurrentOption
->SuppressExpression
= OptionSuppressExpression
;
1462 // Insert to Option list of current Question
1464 InsertTailList (&CurrentStatement
->OptionListHead
, &CurrentOption
->Link
);
1470 case EFI_IFR_NO_SUBMIT_IF_OP
:
1471 case EFI_IFR_INCONSISTENT_IF_OP
:
1473 // Create an Expression node
1475 CurrentExpression
= CreateExpression (CurrentForm
);
1476 CopyMem (&CurrentExpression
->Error
, &((EFI_IFR_INCONSISTENT_IF
*) OpCodeData
)->Error
, sizeof (EFI_STRING_ID
));
1478 if (Operand
== EFI_IFR_NO_SUBMIT_IF_OP
) {
1479 CurrentExpression
->Type
= EFI_HII_EXPRESSION_NO_SUBMIT_IF
;
1480 InsertTailList (&CurrentStatement
->NoSubmitListHead
, &CurrentExpression
->Link
);
1482 CurrentExpression
->Type
= EFI_HII_EXPRESSION_INCONSISTENT_IF
;
1483 InsertTailList (&CurrentStatement
->InconsistentListHead
, &CurrentExpression
->Link
);
1487 case EFI_IFR_SUPPRESS_IF_OP
:
1489 // Question and Option will appear in scope of this OpCode
1491 CurrentExpression
= CreateExpression (CurrentForm
);
1492 CurrentExpression
->Type
= EFI_HII_EXPRESSION_SUPPRESS_IF
;
1493 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1495 if (SuppressForOption
) {
1496 InScopeOptionSuppress
= TRUE
;
1497 OptionSuppressExpression
= CurrentExpression
;
1499 mInScopeSuppress
= TRUE
;
1500 mSuppressExpression
= CurrentExpression
;
1504 case EFI_IFR_GRAY_OUT_IF_OP
:
1506 // Questions will appear in scope of this OpCode
1508 CurrentExpression
= CreateExpression (CurrentForm
);
1509 CurrentExpression
->Type
= EFI_HII_EXPRESSION_GRAY_OUT_IF
;
1510 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1512 mInScopeGrayOut
= TRUE
;
1513 mGrayOutExpression
= CurrentExpression
;
1516 case EFI_IFR_DISABLE_IF_OP
:
1518 // The DisableIf expression should only rely on constant, so it could be
1519 // evaluated at initialization and it will not be queued
1521 CurrentExpression
= AllocateZeroPool (sizeof (FORM_EXPRESSION
));
1522 ASSERT (CurrentExpression
!= NULL
);
1523 CurrentExpression
->Signature
= FORM_EXPRESSION_SIGNATURE
;
1524 CurrentExpression
->Type
= EFI_HII_EXPRESSION_DISABLE_IF
;
1525 InitializeListHead (&CurrentExpression
->OpCodeListHead
);
1527 if (CurrentForm
!= NULL
) {
1529 // This is DisableIf for Question, enqueue it to Form expression list
1531 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1534 mDisableExpression
= CurrentExpression
;
1535 mInScopeDisable
= TRUE
;
1536 OpCodeDisabled
= FALSE
;
1539 // Take a look at next OpCode to see whether current expression consists
1542 if (((EFI_IFR_OP_HEADER
*) (OpCodeData
+ OpCodeLength
))->Scope
== 0) {
1543 SingleOpCodeExpression
= TRUE
;
1550 case EFI_IFR_VALUE_OP
:
1551 CurrentExpression
= CreateExpression (CurrentForm
);
1552 CurrentExpression
->Type
= EFI_HII_EXPRESSION_VALUE
;
1553 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1555 if (InScopeDefault
) {
1557 // Used for default (EFI_IFR_DEFAULT)
1559 CurrentDefault
->ValueExpression
= CurrentExpression
;
1562 // If used for a question, then the question will be read-only
1565 // Make sure CurrentStatement is not NULL.
1566 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1567 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
1569 ASSERT (CurrentStatement
!= NULL
);
1570 CurrentStatement
->ValueExpression
= CurrentExpression
;
1574 case EFI_IFR_RULE_OP
:
1575 CurrentExpression
= CreateExpression (CurrentForm
);
1576 CurrentExpression
->Type
= EFI_HII_EXPRESSION_RULE
;
1578 CurrentExpression
->RuleId
= ((EFI_IFR_RULE
*) OpCodeData
)->RuleId
;
1579 InsertTailList (&CurrentForm
->ExpressionListHead
, &CurrentExpression
->Link
);
1585 case EFI_IFR_IMAGE_OP
:
1587 // Get ScopeOpcode from top of stack
1589 PopScope (&ScopeOpCode
);
1590 PushScope (ScopeOpCode
);
1592 switch (ScopeOpCode
) {
1593 case EFI_IFR_FORM_SET_OP
:
1594 ImageId
= &FormSet
->ImageId
;
1597 case EFI_IFR_FORM_OP
:
1598 ASSERT (CurrentForm
!= NULL
);
1599 ImageId
= &CurrentForm
->ImageId
;
1602 case EFI_IFR_ONE_OF_OPTION_OP
:
1603 ImageId
= &CurrentOption
->ImageId
;
1608 // Make sure CurrentStatement is not NULL.
1609 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1610 // file is wrongly generated by tools such as VFR Compiler.
1612 ASSERT (CurrentStatement
!= NULL
);
1613 ImageId
= &CurrentStatement
->ImageId
;
1617 ASSERT (ImageId
!= NULL
);
1618 CopyMem (ImageId
, &((EFI_IFR_IMAGE
*) OpCodeData
)->Id
, sizeof (EFI_IMAGE_ID
));
1624 case EFI_IFR_REFRESH_OP
:
1625 ASSERT (CurrentStatement
!= NULL
);
1626 CurrentStatement
->RefreshInterval
= ((EFI_IFR_REFRESH
*) OpCodeData
)->RefreshInterval
;
1632 case EFI_IFR_GUID_OP
:
1633 if (CompareGuid (&gEfiIfrTianoGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
1635 // Tiano specific GUIDed opcodes
1637 switch (((EFI_IFR_GUID_LABEL
*) OpCodeData
)->ExtendOpCode
) {
1638 case EFI_IFR_EXTEND_OP_LABEL
:
1640 // just ignore label
1644 case EFI_IFR_EXTEND_OP_BANNER
:
1646 // By SubClass to get Banner Data from Front Page
1648 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
1650 &gBannerData
->Banner
[((EFI_IFR_GUID_BANNER
*) OpCodeData
)->LineNumber
][
1651 ((EFI_IFR_GUID_BANNER
*) OpCodeData
)->Alignment
],
1652 &((EFI_IFR_GUID_BANNER
*) OpCodeData
)->Title
,
1653 sizeof (EFI_STRING_ID
)
1658 case EFI_IFR_EXTEND_OP_CLASS
:
1659 CopyMem (&FormSet
->Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
1662 case EFI_IFR_EXTEND_OP_SUBCLASS
:
1663 CopyMem (&FormSet
->SubClass
, &((EFI_IFR_GUID_SUBCLASS
*) OpCodeData
)->SubClass
, sizeof (UINT16
));
1676 case EFI_IFR_END_OP
:
1677 Status
= PopScope (&ScopeOpCode
);
1678 if (EFI_ERROR (Status
)) {
1683 switch (ScopeOpCode
) {
1684 case EFI_IFR_FORM_SET_OP
:
1686 // End of FormSet, update FormSet IFR binary length
1687 // to stop parsing substantial OpCodes
1689 FormSet
->IfrBinaryLength
= OpCodeOffset
;
1692 case EFI_IFR_FORM_OP
:
1699 case EFI_IFR_ONE_OF_OPTION_OP
:
1703 CurrentOption
= NULL
;
1706 case EFI_IFR_SUBTITLE_OP
:
1707 mInScopeSubtitle
= FALSE
;
1710 case EFI_IFR_NO_SUBMIT_IF_OP
:
1711 case EFI_IFR_INCONSISTENT_IF_OP
:
1713 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1717 case EFI_IFR_SUPPRESS_IF_OP
:
1718 if (SuppressForOption
) {
1719 InScopeOptionSuppress
= FALSE
;
1721 mInScopeSuppress
= FALSE
;
1725 case EFI_IFR_GRAY_OUT_IF_OP
:
1726 mInScopeGrayOut
= FALSE
;
1729 case EFI_IFR_DISABLE_IF_OP
:
1730 mInScopeDisable
= FALSE
;
1731 OpCodeDisabled
= FALSE
;
1734 case EFI_IFR_ONE_OF_OP
:
1735 case EFI_IFR_ORDERED_LIST_OP
:
1736 SuppressForOption
= FALSE
;
1739 case EFI_IFR_DEFAULT_OP
:
1740 InScopeDefault
= FALSE
;
1744 if (IsExpressionOpCode (ScopeOpCode
)) {
1745 if (mInScopeDisable
&& CurrentForm
== NULL
) {
1747 // This is DisableIf expression for Form, it should be a constant expression
1749 Status
= EvaluateExpression (FormSet
, CurrentForm
, CurrentExpression
);
1750 if (EFI_ERROR (Status
)) {
1754 ASSERT (CurrentExpression
!= NULL
);
1755 if (CurrentExpression
->Result
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1756 return EFI_INVALID_PARAMETER
;
1759 OpCodeDisabled
= CurrentExpression
->Result
.Value
.b
;
1761 // DisableIf Expression is only used once and not quequed, free it
1763 DestroyExpression (CurrentExpression
);
1767 // End of current Expression
1769 CurrentExpression
= NULL
;