2 Parser for IFR binary encoding.
4 Copyright (c) 2008 - 2010, 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.
15 #include "HiiDatabase.h"
17 #include "UefiIfrParserExpression.h"
19 UINT16 mStatementIndex
;
21 BOOLEAN mInScopeSubtitle
;
22 BOOLEAN mInScopeSuppress
;
23 BOOLEAN mInScopeGrayOut
;
25 EFI_GUID mFrameworkHiiCompatibilityGuid
= EFI_IFR_FRAMEWORK_GUID
;
26 extern EFI_GUID mTianoHiiIfrGuid
;
29 GetOneOfOptionMapEntryListHead (
30 IN CONST FORM_BROWSER_FORMSET
*FormSet
,
35 ONE_OF_OPTION_MAP
*Map
;
37 Link
= GetFirstNode (&FormSet
->OneOfOptionMapListHead
);
39 while (!IsNull (&FormSet
->OneOfOptionMapListHead
, Link
)) {
40 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
41 if (QuestionId
== Map
->QuestionId
) {
42 return &Map
->OneOfOptionMapEntryListHead
;
44 Link
= GetNextNode (&FormSet
->OneOfOptionMapListHead
, Link
);
51 DestoryOneOfOptionMap (
52 IN LIST_ENTRY
*OneOfOptionMapListHead
55 ONE_OF_OPTION_MAP
*Map
;
56 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
60 while (!IsListEmpty (OneOfOptionMapListHead
)) {
61 Link
= GetFirstNode (OneOfOptionMapListHead
);
63 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
65 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
66 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
68 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
70 RemoveEntryList (Link2
);
75 RemoveEntryList (Link
);
82 Initialize Statement header members.
84 @param OpCodeData Pointer of the raw OpCode data.
85 @param FormSet Pointer of the current FormSe.
86 @param Form Pointer of the current Form.
88 @return The Statement.
91 FORM_BROWSER_STATEMENT
*
94 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
95 IN OUT FORM_BROWSER_FORM
*Form
98 FORM_BROWSER_STATEMENT
*Statement
;
99 EFI_IFR_STATEMENT_HEADER
*StatementHdr
;
103 // We are currently not in a Form Scope, so just skip this Statement
108 Statement
= &FormSet
->StatementBuffer
[mStatementIndex
];
111 InitializeListHead (&Statement
->DefaultListHead
);
112 InitializeListHead (&Statement
->OptionListHead
);
114 Statement
->Signature
= FORM_BROWSER_STATEMENT_SIGNATURE
;
116 Statement
->Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
118 StatementHdr
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
119 CopyMem (&Statement
->Prompt
, &StatementHdr
->Prompt
, sizeof (EFI_STRING_ID
));
120 CopyMem (&Statement
->Help
, &StatementHdr
->Help
, sizeof (EFI_STRING_ID
));
122 Statement
->InSubtitle
= mInScopeSubtitle
;
125 // Insert this Statement into current Form
127 InsertTailList (&Form
->StatementListHead
, &Statement
->Link
);
133 Initialize Question's members.
135 @param OpCodeData Pointer of the raw OpCode data.
136 @param FormSet Pointer of the current FormSet.
137 @param Form Pointer of the current Form.
139 @return The Question.
142 FORM_BROWSER_STATEMENT
*
144 IN UINT8
*OpCodeData
,
145 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
146 IN OUT FORM_BROWSER_FORM
*Form
149 FORM_BROWSER_STATEMENT
*Statement
;
150 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
152 FORMSET_STORAGE
*Storage
;
154 Statement
= CreateStatement (OpCodeData
, FormSet
, Form
);
155 if (Statement
== NULL
) {
159 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
160 CopyMem (&Statement
->QuestionId
, &QuestionHdr
->QuestionId
, sizeof (EFI_QUESTION_ID
));
161 CopyMem (&Statement
->VarStoreId
, &QuestionHdr
->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
162 CopyMem (&Statement
->VarStoreInfo
.VarOffset
, &QuestionHdr
->VarStoreInfo
.VarOffset
, sizeof (UINT16
));
164 if (FormSet
->MaxQuestionId
< QuestionHdr
->QuestionId
) {
165 FormSet
->MaxQuestionId
= QuestionHdr
->QuestionId
;
168 Statement
->QuestionFlags
= QuestionHdr
->Flags
;
170 if (Statement
->VarStoreId
== 0) {
172 // VarStoreId of zero indicates no variable storage
178 // Find Storage for this Question
180 Link
= GetFirstNode (&FormSet
->StorageListHead
);
181 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
182 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
184 if (Storage
->VarStoreId
== Statement
->VarStoreId
) {
185 Statement
->Storage
= Storage
;
189 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
191 ASSERT (Statement
->Storage
!= NULL
);
197 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
199 @param FormSet Pointer of the current FormSet
201 @return Pointer to a FORMSET_STORAGE data structure.
206 IN FORM_BROWSER_FORMSET
*FormSet
209 FORMSET_STORAGE
*Storage
;
211 Storage
= AllocateZeroPool (sizeof (FORMSET_STORAGE
));
212 ASSERT (Storage
!= NULL
);
213 Storage
->Signature
= FORMSET_STORAGE_SIGNATURE
;
214 InsertTailList (&FormSet
->StorageListHead
, &Storage
->Link
);
220 Free resources of a storage
222 @param Storage Pointer of the storage
229 IN FORMSET_STORAGE
*Storage
232 if (Storage
== NULL
) {
236 if (Storage
->Name
!= NULL
) {
237 FreePool (Storage
->Name
);
245 Free resources of a Statement
247 @param Statement Pointer of the Statement
254 IN OUT FORM_BROWSER_STATEMENT
*Statement
258 QUESTION_DEFAULT
*Default
;
259 QUESTION_OPTION
*Option
;
262 // Free Default value List
264 while (!IsListEmpty (&Statement
->DefaultListHead
)) {
265 Link
= GetFirstNode (&Statement
->DefaultListHead
);
266 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
267 RemoveEntryList (&Default
->Link
);
269 gBS
->FreePool (Default
);
275 while (!IsListEmpty (&Statement
->OptionListHead
)) {
276 Link
= GetFirstNode (&Statement
->OptionListHead
);
277 Option
= QUESTION_OPTION_FROM_LINK (Link
);
278 RemoveEntryList (&Option
->Link
);
280 gBS
->FreePool (Option
);
288 Free resources of a Form
290 @param Form Pointer of the Form
297 IN OUT FORM_BROWSER_FORM
*Form
301 FORM_BROWSER_STATEMENT
*Statement
;
304 // Free Statements/Questions
306 while (!IsListEmpty (&Form
->StatementListHead
)) {
307 Link
= GetFirstNode (&Form
->StatementListHead
);
308 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
309 RemoveEntryList (&Statement
->Link
);
311 DestroyStatement (Statement
);
317 gBS
->FreePool (Form
);
322 Free resources allocated for a FormSet
324 @param FormSet Pointer of the FormSet
331 IN OUT FORM_BROWSER_FORMSET
*FormSet
335 FORMSET_STORAGE
*Storage
;
336 FORMSET_DEFAULTSTORE
*DefaultStore
;
337 FORM_BROWSER_FORM
*Form
;
340 // Free IFR binary buffer
342 FreePool (FormSet
->IfrBinaryData
);
345 // Free FormSet Storage
347 if (FormSet
->StorageListHead
.ForwardLink
!= NULL
) {
348 while (!IsListEmpty (&FormSet
->StorageListHead
)) {
349 Link
= GetFirstNode (&FormSet
->StorageListHead
);
350 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
351 RemoveEntryList (&Storage
->Link
);
353 DestroyStorage (Storage
);
358 // Free FormSet Default Store
360 if (FormSet
->DefaultStoreListHead
.ForwardLink
!= NULL
) {
361 while (!IsListEmpty (&FormSet
->DefaultStoreListHead
)) {
362 Link
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
363 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (Link
);
364 RemoveEntryList (&DefaultStore
->Link
);
366 gBS
->FreePool (DefaultStore
);
373 if (FormSet
->FormListHead
.ForwardLink
!= NULL
) {
374 while (!IsListEmpty (&FormSet
->FormListHead
)) {
375 Link
= GetFirstNode (&FormSet
->FormListHead
);
376 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
377 RemoveEntryList (&Form
->Link
);
383 if (FormSet
->StatementBuffer
!= NULL
) {
384 FreePool (FormSet
->StatementBuffer
);
387 DestoryOneOfOptionMap (&FormSet
->OneOfOptionMapListHead
);
389 if (FormSet
->OriginalDefaultVarStoreName
!= NULL
) {
390 FreePool (FormSet
->OriginalDefaultVarStoreName
);
398 Tell whether this Operand is an Expression OpCode or not
400 @param Operand Operand of an IFR OpCode.
402 @retval TRUE This is an Expression OpCode.
403 @retval FALSE Not an Expression OpCode.
411 if (((Operand
>= EFI_IFR_EQ_ID_VAL_OP
) && (Operand
<= EFI_IFR_NOT_OP
)) ||
412 ((Operand
>= EFI_IFR_MATCH_OP
) && (Operand
<= EFI_IFR_SET_OP
)) ||
413 ((Operand
>= EFI_IFR_EQUAL_OP
) && (Operand
<= EFI_IFR_SPAN_OP
)) ||
414 (Operand
== EFI_IFR_CATENATE_OP
) ||
415 (Operand
== EFI_IFR_TO_LOWER_OP
) ||
416 (Operand
== EFI_IFR_TO_UPPER_OP
) ||
417 (Operand
== EFI_IFR_MAP_OP
) ||
418 (Operand
== EFI_IFR_VERSION_OP
) ||
419 (Operand
== EFI_IFR_SECURITY_OP
)) {
428 Calculate number of Statemens(Questions) and Expression OpCodes.
430 @param FormSet The FormSet to be counted.
431 @param NumberOfStatement Number of Statemens(Questions)
432 @param NumberOfExpression Number of Expression OpCodes
439 IN FORM_BROWSER_FORMSET
*FormSet
,
440 IN OUT UINT16
*NumberOfStatement
,
441 IN OUT UINT16
*NumberOfExpression
444 UINT16 StatementCount
;
445 UINT16 ExpressionCount
;
454 while (Offset
< FormSet
->IfrBinaryLength
) {
455 OpCodeData
= FormSet
->IfrBinaryData
+ Offset
;
456 OpCodeLen
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
459 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
)) {
466 *NumberOfStatement
= StatementCount
;
467 *NumberOfExpression
= ExpressionCount
;
472 Parse opcodes in the formset IFR binary.
474 @param FormSet Pointer of the FormSet data structure.
476 @retval EFI_SUCCESS Opcode parse success.
477 @retval Other Opcode parse fail.
482 IN FORM_BROWSER_FORMSET
*FormSet
487 FORM_BROWSER_FORM
*CurrentForm
;
488 FORM_BROWSER_STATEMENT
*CurrentStatement
;
495 FORMSET_STORAGE
*Storage
;
496 FORMSET_DEFAULTSTORE
*DefaultStore
;
497 QUESTION_DEFAULT
*CurrentDefault
;
498 QUESTION_OPTION
*CurrentOption
;
500 UINT16 NumberOfStatement
;
501 UINT16 NumberOfExpression
;
502 EFI_IMAGE_ID
*ImageId
;
503 EFI_HII_VALUE
*Value
;
504 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
505 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
506 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
507 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
509 EFI_IFR_ONE_OF
*OneOfOpcode
;
510 HII_THUNK_CONTEXT
*ThunkContext
;
511 EFI_IFR_FORM_MAP_METHOD
*MapMethod
;
513 mInScopeSubtitle
= FALSE
;
514 mInScopeSuppress
= FALSE
;
515 mInScopeGrayOut
= FALSE
;
516 CurrentDefault
= NULL
;
517 CurrentOption
= NULL
;
519 ThunkContext
= UefiHiiHandleToThunkContext ((CONST HII_THUNK_PRIVATE_DATA
*) mHiiThunkPrivateData
, FormSet
->HiiHandle
);
522 // Set to a invalid value.
524 OneOfType
= (UINT8
) -1;
527 // Get the number of Statements and Expressions
529 CountOpCodes (FormSet
, &NumberOfStatement
, &NumberOfExpression
);
530 FormSet
->NumberOfStatement
= NumberOfStatement
;
533 FormSet
->StatementBuffer
= AllocateZeroPool (NumberOfStatement
* sizeof (FORM_BROWSER_STATEMENT
));
534 if (FormSet
->StatementBuffer
== NULL
) {
535 return EFI_OUT_OF_RESOURCES
;
538 InitializeListHead (&FormSet
->StorageListHead
);
539 InitializeListHead (&FormSet
->DefaultStoreListHead
);
540 InitializeListHead (&FormSet
->FormListHead
);
541 InitializeListHead (&FormSet
->OneOfOptionMapListHead
);
544 CurrentStatement
= NULL
;
549 while (OpCodeOffset
< FormSet
->IfrBinaryLength
) {
550 OpCodeData
= FormSet
->IfrBinaryData
+ OpCodeOffset
;
552 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
553 OpCodeOffset
+= OpCodeLength
;
554 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
555 Scope
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Scope
;
558 // If scope bit set, push onto scope stack
564 if (IsExpressionOpCode (Operand
)) {
573 case EFI_IFR_FORM_SET_OP
:
575 // check the formset GUID
577 if (!CompareGuid ((EFI_GUID
*)(VOID
*)&FormSet
->Guid
, (EFI_GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
)) {
578 return EFI_INVALID_PARAMETER
;
581 CopyMem (&FormSet
->FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
582 CopyMem (&FormSet
->Help
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
585 case EFI_IFR_FORM_OP
:
587 // Create a new Form for this FormSet
589 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
590 ASSERT (CurrentForm
!= NULL
);
591 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
593 InitializeListHead (&CurrentForm
->StatementListHead
);
595 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
596 CopyMem (&CurrentForm
->FormTitle
, &((EFI_IFR_FORM
*) OpCodeData
)->FormTitle
, sizeof (EFI_STRING_ID
));
599 // Insert into Form list of this FormSet
601 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
604 case EFI_IFR_FORM_MAP_OP
:
606 // Create a new Form Map for this FormSet
608 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
609 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
611 InitializeListHead (&CurrentForm
->StatementListHead
);
613 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
614 MapMethod
= (EFI_IFR_FORM_MAP_METHOD
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_MAP
));
617 // FormMap Form must contain at least one Map Method.
619 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
< ((UINTN
) (UINT8
*) (MapMethod
+ 1) - (UINTN
) OpCodeData
)) {
620 return EFI_INVALID_PARAMETER
;
624 // Try to find the standard form map method.
626 while (((UINTN
) (UINT8
*) MapMethod
- (UINTN
) OpCodeData
) < ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
) {
627 if (CompareGuid ((EFI_GUID
*) (VOID
*) &MapMethod
->MethodIdentifier
, &gEfiHiiStandardFormGuid
)) {
628 CopyMem (&CurrentForm
->FormTitle
, &MapMethod
->MethodTitle
, sizeof (EFI_STRING_ID
));
634 // If the standard form map method is not found, the first map method title will be used.
636 if (CurrentForm
->FormTitle
== 0) {
637 MapMethod
= (EFI_IFR_FORM_MAP_METHOD
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_MAP
));
638 CopyMem (&CurrentForm
->FormTitle
, &MapMethod
->MethodTitle
, sizeof (EFI_STRING_ID
));
642 // Insert into Form list of this FormSet
644 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
650 case EFI_IFR_VARSTORE_OP
:
652 // Create a buffer Storage for this FormSet
654 Storage
= CreateStorage (FormSet
);
655 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
657 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
658 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
659 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
661 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
662 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
663 ASSERT (Storage
->Name
!= NULL
);
664 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
665 Storage
->Name
[Index
] = (CHAR16
) AsciiString
[Index
];
670 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
672 // Framework IFR doesn't support Name/Value VarStore opcode
674 if (ThunkContext
!= NULL
&& ThunkContext
->ByFrameworkHiiNewPack
) {
679 // Create a name/value Storage for this FormSet
681 Storage
= CreateStorage (FormSet
);
682 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
684 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
685 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
689 case EFI_IFR_VARSTORE_EFI_OP
:
691 // Create a EFI variable Storage for this FormSet
693 Storage
= CreateStorage (FormSet
);
694 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
696 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
697 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
698 CopyMem (&Storage
->Attributes
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Attributes
, sizeof (UINT32
));
704 case EFI_IFR_DEFAULTSTORE_OP
:
705 DefaultStore
= AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE
));
706 ASSERT (DefaultStore
!= NULL
);
707 DefaultStore
->Signature
= FORMSET_DEFAULTSTORE_SIGNATURE
;
709 CopyMem (&DefaultStore
->DefaultId
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
710 CopyMem (&DefaultStore
->DefaultName
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultName
, sizeof (EFI_STRING_ID
));
713 // Insert to DefaultStore list of this Formset
715 InsertTailList (&FormSet
->DefaultStoreListHead
, &DefaultStore
->Link
);
721 case EFI_IFR_SUBTITLE_OP
:
722 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
723 ASSERT (CurrentStatement
!= NULL
);
724 CurrentStatement
->Flags
= ((EFI_IFR_SUBTITLE
*) OpCodeData
)->Flags
;
727 mInScopeSubtitle
= TRUE
;
731 case EFI_IFR_TEXT_OP
:
732 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
733 ASSERT (CurrentStatement
!= NULL
);
735 CopyMem (&CurrentStatement
->TextTwo
, &((EFI_IFR_TEXT
*) OpCodeData
)->TextTwo
, sizeof (EFI_STRING_ID
));
741 case EFI_IFR_ACTION_OP
:
742 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
743 ASSERT (CurrentStatement
!= NULL
);
745 if (OpCodeLength
== sizeof (EFI_IFR_ACTION_1
)) {
747 // No QuestionConfig present, so no configuration string will be processed
749 CurrentStatement
->QuestionConfig
= 0;
751 CopyMem (&CurrentStatement
->QuestionConfig
, &((EFI_IFR_ACTION
*) OpCodeData
)->QuestionConfig
, sizeof (EFI_STRING_ID
));
755 case EFI_IFR_RESET_BUTTON_OP
:
756 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
757 ASSERT (CurrentStatement
!= NULL
);
758 CopyMem (&CurrentStatement
->DefaultId
, &((EFI_IFR_RESET_BUTTON
*) OpCodeData
)->DefaultId
, sizeof (EFI_DEFAULT_ID
));
762 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
763 ASSERT (CurrentStatement
!= NULL
);
765 CopyMem (&CurrentStatement
->RefFormId
, &((EFI_IFR_REF
*) OpCodeData
)->FormId
, sizeof (EFI_FORM_ID
));
766 if (OpCodeLength
>= sizeof (EFI_IFR_REF2
)) {
767 CopyMem (&CurrentStatement
->RefQuestionId
, &((EFI_IFR_REF2
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
769 if (OpCodeLength
>= sizeof (EFI_IFR_REF3
)) {
770 CopyMem (&CurrentStatement
->RefFormSetId
, &((EFI_IFR_REF3
*) OpCodeData
)->FormSetId
, sizeof (EFI_GUID
));
772 if (OpCodeLength
>= sizeof (EFI_IFR_REF4
)) {
773 CopyMem (&CurrentStatement
->RefDevicePath
, &((EFI_IFR_REF4
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
779 case EFI_IFR_ONE_OF_OP
:
780 case EFI_IFR_NUMERIC_OP
:
781 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
782 ASSERT (CurrentStatement
!= NULL
);
784 CurrentStatement
->Flags
= ((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
;
785 Value
= &CurrentStatement
->HiiValue
;
787 switch (CurrentStatement
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
788 case EFI_IFR_NUMERIC_SIZE_1
:
789 CurrentStatement
->Minimum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MinValue
;
790 CurrentStatement
->Maximum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MaxValue
;
791 CurrentStatement
->Step
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.Step
;
792 CurrentStatement
->StorageWidth
= sizeof (UINT8
);
793 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
796 case EFI_IFR_NUMERIC_SIZE_2
:
797 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MinValue
, sizeof (UINT16
));
798 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MaxValue
, sizeof (UINT16
));
799 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.Step
, sizeof (UINT16
));
800 CurrentStatement
->StorageWidth
= sizeof (UINT16
);
801 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
804 case EFI_IFR_NUMERIC_SIZE_4
:
805 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MinValue
, sizeof (UINT32
));
806 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MaxValue
, sizeof (UINT32
));
807 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.Step
, sizeof (UINT32
));
808 CurrentStatement
->StorageWidth
= sizeof (UINT32
);
809 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
812 case EFI_IFR_NUMERIC_SIZE_8
:
813 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MinValue
, sizeof (UINT64
));
814 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MaxValue
, sizeof (UINT64
));
815 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.Step
, sizeof (UINT64
));
816 CurrentStatement
->StorageWidth
= sizeof (UINT64
);
817 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
824 if (Operand
== EFI_IFR_ONE_OF_OP
) {
825 OneOfOpcode
= (EFI_IFR_ONE_OF
*) OpCodeData
;
826 OneOfType
= (UINT8
) (OneOfOpcode
->Flags
& EFI_IFR_NUMERIC_SIZE
);
830 case EFI_IFR_ORDERED_LIST_OP
:
831 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
832 ASSERT (CurrentStatement
!= NULL
);
834 CurrentStatement
->Flags
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Flags
;
835 CurrentStatement
->MaxContainers
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
836 CurrentStatement
->StorageWidth
= (UINT16
)(CurrentStatement
->MaxContainers
* sizeof (UINT8
));
839 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
840 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
841 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
843 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_OTHER
;
844 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
848 case EFI_IFR_CHECKBOX_OP
:
849 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
850 ASSERT (CurrentStatement
!= NULL
);
852 CurrentStatement
->Flags
= ((EFI_IFR_CHECKBOX
*) OpCodeData
)->Flags
;
853 CurrentStatement
->StorageWidth
= sizeof (BOOLEAN
);
854 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_BOOLEAN
;
858 case EFI_IFR_STRING_OP
:
859 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
860 ASSERT (CurrentStatement
!= NULL
);
863 // MinSize is the minimum number of characters that can be accepted for this opcode,
864 // MaxSize is the maximum number of characters that can be accepted for this opcode.
865 // The characters are stored as Unicode, so the storage width should multiply 2.
867 CurrentStatement
->Minimum
= ((EFI_IFR_STRING
*) OpCodeData
)->MinSize
;
868 CurrentStatement
->Maximum
= ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
;
869 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
870 CurrentStatement
->Flags
= ((EFI_IFR_STRING
*) OpCodeData
)->Flags
;
872 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
873 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
877 case EFI_IFR_PASSWORD_OP
:
878 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
879 ASSERT (CurrentStatement
!= NULL
);
882 // MinSize is the minimum number of characters that can be accepted for this opcode,
883 // MaxSize is the maximum number of characters that can be accepted for this opcode.
884 // The characters are stored as Unicode, so the storage width should multiply 2.
886 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MinSize
, sizeof (UINT16
));
887 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
, sizeof (UINT16
));
888 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
890 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
891 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
895 case EFI_IFR_DATE_OP
:
896 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
897 ASSERT (CurrentStatement
!= NULL
);
899 CurrentStatement
->Flags
= ((EFI_IFR_DATE
*) OpCodeData
)->Flags
;
900 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_DATE
;
904 case EFI_IFR_TIME_OP
:
905 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
906 ASSERT (CurrentStatement
!= NULL
);
908 CurrentStatement
->Flags
= ((EFI_IFR_TIME
*) OpCodeData
)->Flags
;
909 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_TIME
;
916 case EFI_IFR_DEFAULT_OP
:
918 // EFI_IFR_DEFAULT appear in scope of a Question,
919 // It creates a default value for the current question.
920 // A Question may have more than one Default value which have different default types.
922 CurrentDefault
= AllocateZeroPool (sizeof (QUESTION_DEFAULT
));
923 ASSERT (CurrentDefault
!= NULL
);
924 CurrentDefault
->Signature
= QUESTION_DEFAULT_SIGNATURE
;
926 CurrentDefault
->Value
.Type
= ((EFI_IFR_DEFAULT
*) OpCodeData
)->Type
;
927 CopyMem (&CurrentDefault
->DefaultId
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
928 CopyMem (&CurrentDefault
->Value
.Value
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
929 ExtendValueToU64 (&CurrentDefault
->Value
);
932 // Insert to Default Value list of current Question
934 InsertTailList (&CurrentStatement
->DefaultListHead
, &CurrentDefault
->Link
);
941 case EFI_IFR_ONE_OF_OPTION_OP
:
943 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
944 // It create a selection for use in current Question.
946 CurrentOption
= AllocateZeroPool (sizeof (QUESTION_OPTION
));
947 ASSERT (CurrentOption
!= NULL
);
948 CurrentOption
->Signature
= QUESTION_OPTION_SIGNATURE
;
950 CurrentOption
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Flags
;
951 CurrentOption
->Value
.Type
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Type
;
952 CopyMem (&CurrentOption
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Option
, sizeof (EFI_STRING_ID
));
953 CopyMem (&CurrentOption
->Value
.Value
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
954 ExtendValueToU64 (&CurrentOption
->Value
);
957 // Insert to Option list of current Question
959 InsertTailList (&CurrentStatement
->OptionListHead
, &CurrentOption
->Link
);
965 case EFI_IFR_NO_SUBMIT_IF_OP
:
966 case EFI_IFR_INCONSISTENT_IF_OP
:
969 case EFI_IFR_SUPPRESS_IF_OP
:
972 case EFI_IFR_GRAY_OUT_IF_OP
:
975 case EFI_IFR_DISABLE_IF_OP
:
977 // Framework IFR doesn't support DisableIf opcode
979 if (ThunkContext
!= NULL
&& ThunkContext
->ByFrameworkHiiNewPack
) {
986 case EFI_IFR_VALUE_OP
:
987 case EFI_IFR_READ_OP
:
988 case EFI_IFR_WRITE_OP
:
991 case EFI_IFR_RULE_OP
:
997 case EFI_IFR_IMAGE_OP
:
999 // Get ScopeOpcode from top of stack
1001 PopScope (&ScopeOpCode
);
1002 PushScope (ScopeOpCode
);
1004 switch (ScopeOpCode
) {
1005 case EFI_IFR_FORM_SET_OP
:
1006 ImageId
= &FormSet
->ImageId
;
1009 case EFI_IFR_FORM_OP
:
1010 case EFI_IFR_FORM_MAP_OP
:
1011 ImageId
= &CurrentForm
->ImageId
;
1014 case EFI_IFR_ONE_OF_OPTION_OP
:
1015 ImageId
= &CurrentOption
->ImageId
;
1020 // Make sure CurrentStatement is not NULL.
1021 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1022 // file is wrongly generated by tools such as VFR Compiler.
1024 ASSERT (CurrentStatement
!= NULL
);
1025 ImageId
= &CurrentStatement
->ImageId
;
1029 ASSERT (ImageId
!= NULL
);
1030 CopyMem (ImageId
, &((EFI_IFR_IMAGE
*) OpCodeData
)->Id
, sizeof (EFI_IMAGE_ID
));
1036 case EFI_IFR_REFRESH_OP
:
1037 ASSERT (CurrentStatement
!= NULL
);
1038 CurrentStatement
->RefreshInterval
= ((EFI_IFR_REFRESH
*) OpCodeData
)->RefreshInterval
;
1044 case EFI_IFR_GUID_OP
:
1045 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCodeData
;
1047 if (CompareGuid (&mTianoHiiIfrGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
1049 // Tiano specific GUIDed opcodes
1051 switch (((EFI_IFR_GUID_LABEL
*) OpCodeData
)->ExtendOpCode
) {
1052 case EFI_IFR_EXTEND_OP_LABEL
:
1054 // just ignore label
1059 case EFI_IFR_EXTEND_OP_CLASS
:
1060 CopyMem (&FormSet
->Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
1063 case EFI_IFR_EXTEND_OP_SUBCLASS
:
1064 CopyMem (&FormSet
->SubClass
, &((EFI_IFR_GUID_SUBCLASS
*) OpCodeData
)->SubClass
, sizeof (UINT16
));
1070 } else if (CompareGuid ((EFI_GUID
*)(VOID
*)&OptionMap
->Guid
, &mFrameworkHiiCompatibilityGuid
)) {
1071 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
1072 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (FormSet
, OptionMap
->QuestionId
);
1073 if (OneOfOptinMapEntryListHead
== NULL
) {
1074 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
1075 ASSERT (OneOfOptionMap
!= NULL
);
1077 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
1078 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
1081 // Make sure OneOfType is initialized.
1083 ASSERT (OneOfType
!= (UINT8
) -1);
1084 OneOfOptionMap
->ValueType
= OneOfType
;
1085 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
1086 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
1087 InsertTailList (&FormSet
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
1089 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
1090 ASSERT (OneOfOptionMapEntry
!= NULL
);
1092 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
1093 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
1094 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1096 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
1104 case EFI_IFR_END_OP
:
1105 Status
= PopScope (&ScopeOpCode
);
1106 if (EFI_ERROR (Status
)) {
1111 switch (ScopeOpCode
) {
1112 case EFI_IFR_FORM_SET_OP
:
1114 // End of FormSet, update FormSet IFR binary length
1115 // to stop parsing substantial OpCodes
1117 FormSet
->IfrBinaryLength
= OpCodeOffset
;
1120 case EFI_IFR_FORM_OP
:
1121 case EFI_IFR_FORM_MAP_OP
:
1128 case EFI_IFR_ONE_OF_OPTION_OP
:
1132 CurrentOption
= NULL
;
1135 case EFI_IFR_SUBTITLE_OP
:
1136 mInScopeSubtitle
= FALSE
;
1139 case EFI_IFR_NO_SUBMIT_IF_OP
:
1140 case EFI_IFR_INCONSISTENT_IF_OP
:
1142 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1146 case EFI_IFR_GRAY_OUT_IF_OP
:
1147 mInScopeGrayOut
= FALSE
;
1151 if (IsExpressionOpCode (ScopeOpCode
)) {