2 Parser for IFR binary encoding.
4 Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
5 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 Find the question's OneOfOptionMap list in FormSet
30 based on the input question Id.
32 @param FormSet FormSet context.
33 @param QuestionId Unique ID to specicy the question in FormSet.
35 @return the found OneOfOptionMap list. If not found, NULL will return.
38 GetOneOfOptionMapEntryListHead (
39 IN CONST FORM_BROWSER_FORMSET
*FormSet
,
44 ONE_OF_OPTION_MAP
*Map
;
46 Link
= GetFirstNode (&FormSet
->OneOfOptionMapListHead
);
48 while (!IsNull (&FormSet
->OneOfOptionMapListHead
, Link
)) {
49 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
50 if (QuestionId
== Map
->QuestionId
) {
51 return &Map
->OneOfOptionMapEntryListHead
;
53 Link
= GetNextNode (&FormSet
->OneOfOptionMapListHead
, Link
);
60 Free OneOfOption map list.
62 @param OneOfOptionMapListHead Pointer to list header of OneOfOptionMap list.
66 DestoryOneOfOptionMap (
67 IN LIST_ENTRY
*OneOfOptionMapListHead
70 ONE_OF_OPTION_MAP
*Map
;
71 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
75 while (!IsListEmpty (OneOfOptionMapListHead
)) {
76 Link
= GetFirstNode (OneOfOptionMapListHead
);
78 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
80 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
81 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
83 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
85 RemoveEntryList (Link2
);
90 RemoveEntryList (Link
);
97 Initialize Statement header members.
99 @param OpCodeData Pointer of the raw OpCode data.
100 @param FormSet Pointer of the current FormSe.
101 @param Form Pointer of the current Form.
103 @return The Statement.
106 FORM_BROWSER_STATEMENT
*
108 IN UINT8
*OpCodeData
,
109 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
110 IN OUT FORM_BROWSER_FORM
*Form
113 FORM_BROWSER_STATEMENT
*Statement
;
114 EFI_IFR_STATEMENT_HEADER
*StatementHdr
;
118 // We are currently not in a Form Scope, so just skip this Statement
123 Statement
= &FormSet
->StatementBuffer
[mStatementIndex
];
126 InitializeListHead (&Statement
->DefaultListHead
);
127 InitializeListHead (&Statement
->OptionListHead
);
129 Statement
->Signature
= FORM_BROWSER_STATEMENT_SIGNATURE
;
131 Statement
->Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
133 StatementHdr
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
134 CopyMem (&Statement
->Prompt
, &StatementHdr
->Prompt
, sizeof (EFI_STRING_ID
));
135 CopyMem (&Statement
->Help
, &StatementHdr
->Help
, sizeof (EFI_STRING_ID
));
137 Statement
->InSubtitle
= mInScopeSubtitle
;
140 // Insert this Statement into current Form
142 InsertTailList (&Form
->StatementListHead
, &Statement
->Link
);
148 Initialize Question's members.
150 @param OpCodeData Pointer of the raw OpCode data.
151 @param FormSet Pointer of the current FormSet.
152 @param Form Pointer of the current Form.
154 @return The Question.
157 FORM_BROWSER_STATEMENT
*
159 IN UINT8
*OpCodeData
,
160 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
161 IN OUT FORM_BROWSER_FORM
*Form
164 FORM_BROWSER_STATEMENT
*Statement
;
165 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
167 FORMSET_STORAGE
*Storage
;
169 Statement
= CreateStatement (OpCodeData
, FormSet
, Form
);
170 if (Statement
== NULL
) {
174 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
175 CopyMem (&Statement
->QuestionId
, &QuestionHdr
->QuestionId
, sizeof (EFI_QUESTION_ID
));
176 CopyMem (&Statement
->VarStoreId
, &QuestionHdr
->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
177 CopyMem (&Statement
->VarStoreInfo
.VarOffset
, &QuestionHdr
->VarStoreInfo
.VarOffset
, sizeof (UINT16
));
179 if (FormSet
->MaxQuestionId
< QuestionHdr
->QuestionId
) {
180 FormSet
->MaxQuestionId
= QuestionHdr
->QuestionId
;
183 Statement
->QuestionFlags
= QuestionHdr
->Flags
;
185 if (Statement
->VarStoreId
== 0) {
187 // VarStoreId of zero indicates no variable storage
193 // Find Storage for this Question
195 Link
= GetFirstNode (&FormSet
->StorageListHead
);
196 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
197 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
199 if (Storage
->VarStoreId
== Statement
->VarStoreId
) {
200 Statement
->Storage
= Storage
;
204 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
206 ASSERT (Statement
->Storage
!= NULL
);
212 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
214 @param FormSet Pointer of the current FormSet
216 @return Pointer to a FORMSET_STORAGE data structure.
221 IN FORM_BROWSER_FORMSET
*FormSet
224 FORMSET_STORAGE
*Storage
;
226 Storage
= AllocateZeroPool (sizeof (FORMSET_STORAGE
));
227 ASSERT (Storage
!= NULL
);
228 Storage
->Signature
= FORMSET_STORAGE_SIGNATURE
;
229 InsertTailList (&FormSet
->StorageListHead
, &Storage
->Link
);
235 Free resources of a storage
237 @param Storage Pointer of the storage
244 IN FORMSET_STORAGE
*Storage
247 if (Storage
== NULL
) {
251 if (Storage
->Name
!= NULL
) {
252 FreePool (Storage
->Name
);
260 Free resources of a Statement
262 @param Statement Pointer of the Statement
269 IN OUT FORM_BROWSER_STATEMENT
*Statement
273 QUESTION_DEFAULT
*Default
;
274 QUESTION_OPTION
*Option
;
277 // Free Default value List
279 while (!IsListEmpty (&Statement
->DefaultListHead
)) {
280 Link
= GetFirstNode (&Statement
->DefaultListHead
);
281 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
282 RemoveEntryList (&Default
->Link
);
284 gBS
->FreePool (Default
);
290 while (!IsListEmpty (&Statement
->OptionListHead
)) {
291 Link
= GetFirstNode (&Statement
->OptionListHead
);
292 Option
= QUESTION_OPTION_FROM_LINK (Link
);
293 RemoveEntryList (&Option
->Link
);
295 gBS
->FreePool (Option
);
303 Free resources of a Form
305 @param Form Pointer of the Form
312 IN OUT FORM_BROWSER_FORM
*Form
316 FORM_BROWSER_STATEMENT
*Statement
;
319 // Free Statements/Questions
321 while (!IsListEmpty (&Form
->StatementListHead
)) {
322 Link
= GetFirstNode (&Form
->StatementListHead
);
323 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
324 RemoveEntryList (&Statement
->Link
);
326 DestroyStatement (Statement
);
332 gBS
->FreePool (Form
);
337 Free resources allocated for a FormSet
339 @param FormSet Pointer of the FormSet
346 IN OUT FORM_BROWSER_FORMSET
*FormSet
350 FORMSET_STORAGE
*Storage
;
351 FORMSET_DEFAULTSTORE
*DefaultStore
;
352 FORM_BROWSER_FORM
*Form
;
355 // Free IFR binary buffer
357 FreePool (FormSet
->IfrBinaryData
);
360 // Free FormSet Storage
362 if (FormSet
->StorageListHead
.ForwardLink
!= NULL
) {
363 while (!IsListEmpty (&FormSet
->StorageListHead
)) {
364 Link
= GetFirstNode (&FormSet
->StorageListHead
);
365 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
366 RemoveEntryList (&Storage
->Link
);
368 DestroyStorage (Storage
);
373 // Free FormSet Default Store
375 if (FormSet
->DefaultStoreListHead
.ForwardLink
!= NULL
) {
376 while (!IsListEmpty (&FormSet
->DefaultStoreListHead
)) {
377 Link
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
378 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (Link
);
379 RemoveEntryList (&DefaultStore
->Link
);
381 gBS
->FreePool (DefaultStore
);
388 if (FormSet
->FormListHead
.ForwardLink
!= NULL
) {
389 while (!IsListEmpty (&FormSet
->FormListHead
)) {
390 Link
= GetFirstNode (&FormSet
->FormListHead
);
391 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
392 RemoveEntryList (&Form
->Link
);
398 if (FormSet
->StatementBuffer
!= NULL
) {
399 FreePool (FormSet
->StatementBuffer
);
402 DestoryOneOfOptionMap (&FormSet
->OneOfOptionMapListHead
);
404 if (FormSet
->OriginalDefaultVarStoreName
!= NULL
) {
405 FreePool (FormSet
->OriginalDefaultVarStoreName
);
413 Tell whether this Operand is an Expression OpCode or not
415 @param Operand Operand of an IFR OpCode.
417 @retval TRUE This is an Expression OpCode.
418 @retval FALSE Not an Expression OpCode.
426 if (((Operand
>= EFI_IFR_EQ_ID_VAL_OP
) && (Operand
<= EFI_IFR_NOT_OP
)) ||
427 ((Operand
>= EFI_IFR_MATCH_OP
) && (Operand
<= EFI_IFR_SET_OP
)) ||
428 ((Operand
>= EFI_IFR_EQUAL_OP
) && (Operand
<= EFI_IFR_SPAN_OP
)) ||
429 (Operand
== EFI_IFR_CATENATE_OP
) ||
430 (Operand
== EFI_IFR_TO_LOWER_OP
) ||
431 (Operand
== EFI_IFR_TO_UPPER_OP
) ||
432 (Operand
== EFI_IFR_MAP_OP
) ||
433 (Operand
== EFI_IFR_VERSION_OP
) ||
434 (Operand
== EFI_IFR_SECURITY_OP
)) {
443 Calculate number of Statemens(Questions) and Expression OpCodes.
445 @param FormSet The FormSet to be counted.
446 @param NumberOfStatement Number of Statemens(Questions)
447 @param NumberOfExpression Number of Expression OpCodes
454 IN FORM_BROWSER_FORMSET
*FormSet
,
455 IN OUT UINT16
*NumberOfStatement
,
456 IN OUT UINT16
*NumberOfExpression
459 UINT16 StatementCount
;
460 UINT16 ExpressionCount
;
469 while (Offset
< FormSet
->IfrBinaryLength
) {
470 OpCodeData
= FormSet
->IfrBinaryData
+ Offset
;
471 OpCodeLen
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
474 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
)) {
481 *NumberOfStatement
= StatementCount
;
482 *NumberOfExpression
= ExpressionCount
;
487 Parse opcodes in the formset IFR binary.
489 @param FormSet Pointer of the FormSet data structure.
491 @retval EFI_SUCCESS Opcode parse success.
492 @retval Other Opcode parse fail.
497 IN FORM_BROWSER_FORMSET
*FormSet
502 FORM_BROWSER_FORM
*CurrentForm
;
503 FORM_BROWSER_STATEMENT
*CurrentStatement
;
510 FORMSET_STORAGE
*Storage
;
511 FORMSET_DEFAULTSTORE
*DefaultStore
;
512 QUESTION_DEFAULT
*CurrentDefault
;
513 QUESTION_OPTION
*CurrentOption
;
515 UINT16 NumberOfStatement
;
516 UINT16 NumberOfExpression
;
517 EFI_IMAGE_ID
*ImageId
;
518 EFI_HII_VALUE
*Value
;
519 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
520 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
521 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
522 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
524 EFI_IFR_ONE_OF
*OneOfOpcode
;
525 HII_THUNK_CONTEXT
*ThunkContext
;
526 EFI_IFR_FORM_MAP_METHOD
*MapMethod
;
528 mInScopeSubtitle
= FALSE
;
529 mInScopeSuppress
= FALSE
;
530 mInScopeGrayOut
= FALSE
;
531 CurrentDefault
= NULL
;
532 CurrentOption
= NULL
;
534 ThunkContext
= UefiHiiHandleToThunkContext ((CONST HII_THUNK_PRIVATE_DATA
*) mHiiThunkPrivateData
, FormSet
->HiiHandle
);
537 // Set to a invalid value.
539 OneOfType
= (UINT8
) -1;
542 // Get the number of Statements and Expressions
544 CountOpCodes (FormSet
, &NumberOfStatement
, &NumberOfExpression
);
545 FormSet
->NumberOfStatement
= NumberOfStatement
;
548 FormSet
->StatementBuffer
= AllocateZeroPool (NumberOfStatement
* sizeof (FORM_BROWSER_STATEMENT
));
549 if (FormSet
->StatementBuffer
== NULL
) {
550 return EFI_OUT_OF_RESOURCES
;
553 InitializeListHead (&FormSet
->StorageListHead
);
554 InitializeListHead (&FormSet
->DefaultStoreListHead
);
555 InitializeListHead (&FormSet
->FormListHead
);
556 InitializeListHead (&FormSet
->OneOfOptionMapListHead
);
559 CurrentStatement
= NULL
;
564 while (OpCodeOffset
< FormSet
->IfrBinaryLength
) {
565 OpCodeData
= FormSet
->IfrBinaryData
+ OpCodeOffset
;
567 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
568 OpCodeOffset
+= OpCodeLength
;
569 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
570 Scope
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Scope
;
573 // If scope bit set, push onto scope stack
579 if (IsExpressionOpCode (Operand
)) {
588 case EFI_IFR_FORM_SET_OP
:
590 // check the formset GUID
592 if (!CompareGuid ((EFI_GUID
*)(VOID
*)&FormSet
->Guid
, (EFI_GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
)) {
593 return EFI_INVALID_PARAMETER
;
596 CopyMem (&FormSet
->FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
597 CopyMem (&FormSet
->Help
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
600 case EFI_IFR_FORM_OP
:
602 // Create a new Form for this FormSet
604 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
605 ASSERT (CurrentForm
!= NULL
);
606 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
608 InitializeListHead (&CurrentForm
->StatementListHead
);
610 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
611 CopyMem (&CurrentForm
->FormTitle
, &((EFI_IFR_FORM
*) OpCodeData
)->FormTitle
, sizeof (EFI_STRING_ID
));
614 // Insert into Form list of this FormSet
616 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
619 case EFI_IFR_FORM_MAP_OP
:
621 // Create a new Form Map for this FormSet
623 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
624 ASSERT (CurrentForm
!= NULL
);
625 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
627 InitializeListHead (&CurrentForm
->StatementListHead
);
629 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
630 MapMethod
= (EFI_IFR_FORM_MAP_METHOD
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_MAP
));
633 // FormMap Form must contain at least one Map Method.
635 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
< ((UINTN
) (UINT8
*) (MapMethod
+ 1) - (UINTN
) OpCodeData
)) {
636 return EFI_INVALID_PARAMETER
;
640 // Try to find the standard form map method.
642 while (((UINTN
) (UINT8
*) MapMethod
- (UINTN
) OpCodeData
) < ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
) {
643 if (CompareGuid ((EFI_GUID
*) (VOID
*) &MapMethod
->MethodIdentifier
, &gEfiHiiStandardFormGuid
)) {
644 CopyMem (&CurrentForm
->FormTitle
, &MapMethod
->MethodTitle
, sizeof (EFI_STRING_ID
));
650 // If the standard form map method is not found, the first map method title will be used.
652 if (CurrentForm
->FormTitle
== 0) {
653 MapMethod
= (EFI_IFR_FORM_MAP_METHOD
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_MAP
));
654 CopyMem (&CurrentForm
->FormTitle
, &MapMethod
->MethodTitle
, sizeof (EFI_STRING_ID
));
658 // Insert into Form list of this FormSet
660 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
666 case EFI_IFR_VARSTORE_OP
:
668 // Create a buffer Storage for this FormSet
670 Storage
= CreateStorage (FormSet
);
671 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
673 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
674 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
675 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
677 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
678 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
679 ASSERT (Storage
->Name
!= NULL
);
680 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
681 Storage
->Name
[Index
] = (CHAR16
) AsciiString
[Index
];
686 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
688 // Framework IFR doesn't support Name/Value VarStore opcode
690 if (ThunkContext
!= NULL
&& ThunkContext
->ByFrameworkHiiNewPack
) {
695 // Create a name/value Storage for this FormSet
697 Storage
= CreateStorage (FormSet
);
698 Storage
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
700 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
701 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
705 case EFI_IFR_VARSTORE_EFI_OP
:
707 // Create a EFI variable Storage for this FormSet
709 Storage
= CreateStorage (FormSet
);
710 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
712 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
713 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
714 CopyMem (&Storage
->Attributes
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Attributes
, sizeof (UINT32
));
720 case EFI_IFR_DEFAULTSTORE_OP
:
721 DefaultStore
= AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE
));
722 ASSERT (DefaultStore
!= NULL
);
723 DefaultStore
->Signature
= FORMSET_DEFAULTSTORE_SIGNATURE
;
725 CopyMem (&DefaultStore
->DefaultId
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
726 CopyMem (&DefaultStore
->DefaultName
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultName
, sizeof (EFI_STRING_ID
));
729 // Insert to DefaultStore list of this Formset
731 InsertTailList (&FormSet
->DefaultStoreListHead
, &DefaultStore
->Link
);
737 case EFI_IFR_SUBTITLE_OP
:
738 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
739 ASSERT (CurrentStatement
!= NULL
);
740 CurrentStatement
->Flags
= ((EFI_IFR_SUBTITLE
*) OpCodeData
)->Flags
;
743 mInScopeSubtitle
= TRUE
;
747 case EFI_IFR_TEXT_OP
:
748 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
749 ASSERT (CurrentStatement
!= NULL
);
751 CopyMem (&CurrentStatement
->TextTwo
, &((EFI_IFR_TEXT
*) OpCodeData
)->TextTwo
, sizeof (EFI_STRING_ID
));
757 case EFI_IFR_ACTION_OP
:
758 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
759 ASSERT (CurrentStatement
!= NULL
);
761 if (OpCodeLength
== sizeof (EFI_IFR_ACTION_1
)) {
763 // No QuestionConfig present, so no configuration string will be processed
765 CurrentStatement
->QuestionConfig
= 0;
767 CopyMem (&CurrentStatement
->QuestionConfig
, &((EFI_IFR_ACTION
*) OpCodeData
)->QuestionConfig
, sizeof (EFI_STRING_ID
));
771 case EFI_IFR_RESET_BUTTON_OP
:
772 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
773 ASSERT (CurrentStatement
!= NULL
);
774 CopyMem (&CurrentStatement
->DefaultId
, &((EFI_IFR_RESET_BUTTON
*) OpCodeData
)->DefaultId
, sizeof (EFI_DEFAULT_ID
));
778 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
779 ASSERT (CurrentStatement
!= NULL
);
781 CopyMem (&CurrentStatement
->RefFormId
, &((EFI_IFR_REF
*) OpCodeData
)->FormId
, sizeof (EFI_FORM_ID
));
782 if (OpCodeLength
>= sizeof (EFI_IFR_REF2
)) {
783 CopyMem (&CurrentStatement
->RefQuestionId
, &((EFI_IFR_REF2
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
785 if (OpCodeLength
>= sizeof (EFI_IFR_REF3
)) {
786 CopyMem (&CurrentStatement
->RefFormSetId
, &((EFI_IFR_REF3
*) OpCodeData
)->FormSetId
, sizeof (EFI_GUID
));
788 if (OpCodeLength
>= sizeof (EFI_IFR_REF4
)) {
789 CopyMem (&CurrentStatement
->RefDevicePath
, &((EFI_IFR_REF4
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
795 case EFI_IFR_ONE_OF_OP
:
796 case EFI_IFR_NUMERIC_OP
:
797 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
798 ASSERT (CurrentStatement
!= NULL
);
800 CurrentStatement
->Flags
= ((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
;
801 Value
= &CurrentStatement
->HiiValue
;
803 switch (CurrentStatement
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
804 case EFI_IFR_NUMERIC_SIZE_1
:
805 CurrentStatement
->Minimum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MinValue
;
806 CurrentStatement
->Maximum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MaxValue
;
807 CurrentStatement
->Step
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.Step
;
808 CurrentStatement
->StorageWidth
= (UINT16
) sizeof (UINT8
);
809 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
812 case EFI_IFR_NUMERIC_SIZE_2
:
813 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MinValue
, sizeof (UINT16
));
814 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MaxValue
, sizeof (UINT16
));
815 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.Step
, sizeof (UINT16
));
816 CurrentStatement
->StorageWidth
= (UINT16
) sizeof (UINT16
);
817 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
820 case EFI_IFR_NUMERIC_SIZE_4
:
821 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MinValue
, sizeof (UINT32
));
822 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MaxValue
, sizeof (UINT32
));
823 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.Step
, sizeof (UINT32
));
824 CurrentStatement
->StorageWidth
= (UINT16
) sizeof (UINT32
);
825 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
828 case EFI_IFR_NUMERIC_SIZE_8
:
829 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MinValue
, sizeof (UINT64
));
830 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MaxValue
, sizeof (UINT64
));
831 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.Step
, sizeof (UINT64
));
832 CurrentStatement
->StorageWidth
= (UINT16
) sizeof (UINT64
);
833 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
840 if (Operand
== EFI_IFR_ONE_OF_OP
) {
841 OneOfOpcode
= (EFI_IFR_ONE_OF
*) OpCodeData
;
842 OneOfType
= (UINT8
) (OneOfOpcode
->Flags
& EFI_IFR_NUMERIC_SIZE
);
846 case EFI_IFR_ORDERED_LIST_OP
:
847 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
848 ASSERT (CurrentStatement
!= NULL
);
850 CurrentStatement
->Flags
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Flags
;
851 CurrentStatement
->MaxContainers
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
852 CurrentStatement
->StorageWidth
= (UINT16
)(CurrentStatement
->MaxContainers
* sizeof (UINT8
));
855 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
856 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
857 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
859 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_OTHER
;
860 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
864 case EFI_IFR_CHECKBOX_OP
:
865 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
866 ASSERT (CurrentStatement
!= NULL
);
868 CurrentStatement
->Flags
= ((EFI_IFR_CHECKBOX
*) OpCodeData
)->Flags
;
869 CurrentStatement
->StorageWidth
= (UINT16
) sizeof (BOOLEAN
);
870 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_BOOLEAN
;
874 case EFI_IFR_STRING_OP
:
875 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
876 ASSERT (CurrentStatement
!= NULL
);
879 // MinSize is the minimum number of characters that can be accepted for this opcode,
880 // MaxSize is the maximum number of characters that can be accepted for this opcode.
881 // The characters are stored as Unicode, so the storage width should multiply 2.
883 CurrentStatement
->Minimum
= ((EFI_IFR_STRING
*) OpCodeData
)->MinSize
;
884 CurrentStatement
->Maximum
= ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
;
885 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
886 CurrentStatement
->Flags
= ((EFI_IFR_STRING
*) OpCodeData
)->Flags
;
888 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
889 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
893 case EFI_IFR_PASSWORD_OP
:
894 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
895 ASSERT (CurrentStatement
!= NULL
);
898 // MinSize is the minimum number of characters that can be accepted for this opcode,
899 // MaxSize is the maximum number of characters that can be accepted for this opcode.
900 // The characters are stored as Unicode, so the storage width should multiply 2.
902 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MinSize
, sizeof (UINT16
));
903 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
, sizeof (UINT16
));
904 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
906 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
907 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
911 case EFI_IFR_DATE_OP
:
912 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
913 ASSERT (CurrentStatement
!= NULL
);
915 CurrentStatement
->Flags
= ((EFI_IFR_DATE
*) OpCodeData
)->Flags
;
916 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_DATE
;
920 case EFI_IFR_TIME_OP
:
921 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
922 ASSERT (CurrentStatement
!= NULL
);
924 CurrentStatement
->Flags
= ((EFI_IFR_TIME
*) OpCodeData
)->Flags
;
925 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_TIME
;
932 case EFI_IFR_DEFAULT_OP
:
934 // EFI_IFR_DEFAULT appear in scope of a Question,
935 // It creates a default value for the current question.
936 // A Question may have more than one Default value which have different default types.
938 CurrentDefault
= AllocateZeroPool (sizeof (QUESTION_DEFAULT
));
939 ASSERT (CurrentDefault
!= NULL
);
940 CurrentDefault
->Signature
= QUESTION_DEFAULT_SIGNATURE
;
942 CurrentDefault
->Value
.Type
= ((EFI_IFR_DEFAULT
*) OpCodeData
)->Type
;
943 CopyMem (&CurrentDefault
->DefaultId
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
944 CopyMem (&CurrentDefault
->Value
.Value
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
945 ExtendValueToU64 (&CurrentDefault
->Value
);
948 // Insert to Default Value list of current Question
950 InsertTailList (&CurrentStatement
->DefaultListHead
, &CurrentDefault
->Link
);
957 case EFI_IFR_ONE_OF_OPTION_OP
:
959 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
960 // It create a selection for use in current Question.
962 CurrentOption
= AllocateZeroPool (sizeof (QUESTION_OPTION
));
963 ASSERT (CurrentOption
!= NULL
);
964 CurrentOption
->Signature
= QUESTION_OPTION_SIGNATURE
;
966 CurrentOption
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Flags
;
967 CurrentOption
->Value
.Type
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Type
;
968 CopyMem (&CurrentOption
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Option
, sizeof (EFI_STRING_ID
));
969 CopyMem (&CurrentOption
->Value
.Value
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
970 ExtendValueToU64 (&CurrentOption
->Value
);
973 // Insert to Option list of current Question
975 InsertTailList (&CurrentStatement
->OptionListHead
, &CurrentOption
->Link
);
981 case EFI_IFR_NO_SUBMIT_IF_OP
:
982 case EFI_IFR_INCONSISTENT_IF_OP
:
985 case EFI_IFR_SUPPRESS_IF_OP
:
988 case EFI_IFR_GRAY_OUT_IF_OP
:
991 case EFI_IFR_DISABLE_IF_OP
:
993 // Framework IFR doesn't support DisableIf opcode
995 if (ThunkContext
!= NULL
&& ThunkContext
->ByFrameworkHiiNewPack
) {
1002 case EFI_IFR_VALUE_OP
:
1003 case EFI_IFR_READ_OP
:
1004 case EFI_IFR_WRITE_OP
:
1007 case EFI_IFR_RULE_OP
:
1013 case EFI_IFR_IMAGE_OP
:
1015 // Get ScopeOpcode from top of stack
1017 PopScope (&ScopeOpCode
);
1018 PushScope (ScopeOpCode
);
1020 switch (ScopeOpCode
) {
1021 case EFI_IFR_FORM_SET_OP
:
1022 ImageId
= &FormSet
->ImageId
;
1025 case EFI_IFR_FORM_OP
:
1026 case EFI_IFR_FORM_MAP_OP
:
1027 ImageId
= &CurrentForm
->ImageId
;
1030 case EFI_IFR_ONE_OF_OPTION_OP
:
1031 ImageId
= &CurrentOption
->ImageId
;
1036 // Make sure CurrentStatement is not NULL.
1037 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1038 // file is wrongly generated by tools such as VFR Compiler.
1040 ASSERT (CurrentStatement
!= NULL
);
1041 ImageId
= &CurrentStatement
->ImageId
;
1045 ASSERT (ImageId
!= NULL
);
1046 CopyMem (ImageId
, &((EFI_IFR_IMAGE
*) OpCodeData
)->Id
, sizeof (EFI_IMAGE_ID
));
1052 case EFI_IFR_REFRESH_OP
:
1053 ASSERT (CurrentStatement
!= NULL
);
1054 CurrentStatement
->RefreshInterval
= ((EFI_IFR_REFRESH
*) OpCodeData
)->RefreshInterval
;
1060 case EFI_IFR_GUID_OP
:
1061 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCodeData
;
1063 if (CompareGuid (&mTianoHiiIfrGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
1065 // Tiano specific GUIDed opcodes
1067 switch (((EFI_IFR_GUID_LABEL
*) OpCodeData
)->ExtendOpCode
) {
1068 case EFI_IFR_EXTEND_OP_LABEL
:
1070 // just ignore label
1075 case EFI_IFR_EXTEND_OP_CLASS
:
1076 CopyMem (&FormSet
->Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
1079 case EFI_IFR_EXTEND_OP_SUBCLASS
:
1080 CopyMem (&FormSet
->SubClass
, &((EFI_IFR_GUID_SUBCLASS
*) OpCodeData
)->SubClass
, sizeof (UINT16
));
1086 } else if (CompareGuid ((EFI_GUID
*)(VOID
*)&OptionMap
->Guid
, &mFrameworkHiiCompatibilityGuid
)) {
1087 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
1088 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (FormSet
, OptionMap
->QuestionId
);
1089 if (OneOfOptinMapEntryListHead
== NULL
) {
1090 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
1091 ASSERT (OneOfOptionMap
!= NULL
);
1093 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
1094 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
1097 // Make sure OneOfType is initialized.
1099 ASSERT (OneOfType
!= (UINT8
) -1);
1100 OneOfOptionMap
->ValueType
= OneOfType
;
1101 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
1102 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
1103 InsertTailList (&FormSet
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
1105 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
1106 ASSERT (OneOfOptionMapEntry
!= NULL
);
1108 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
1109 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
1110 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1112 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
1120 case EFI_IFR_END_OP
:
1121 Status
= PopScope (&ScopeOpCode
);
1122 if (EFI_ERROR (Status
)) {
1127 switch (ScopeOpCode
) {
1128 case EFI_IFR_FORM_SET_OP
:
1130 // End of FormSet, update FormSet IFR binary length
1131 // to stop parsing substantial OpCodes
1133 FormSet
->IfrBinaryLength
= OpCodeOffset
;
1136 case EFI_IFR_FORM_OP
:
1137 case EFI_IFR_FORM_MAP_OP
:
1144 case EFI_IFR_ONE_OF_OPTION_OP
:
1148 CurrentOption
= NULL
;
1151 case EFI_IFR_SUBTITLE_OP
:
1152 mInScopeSubtitle
= FALSE
;
1155 case EFI_IFR_NO_SUBMIT_IF_OP
:
1156 case EFI_IFR_INCONSISTENT_IF_OP
:
1158 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1162 case EFI_IFR_GRAY_OUT_IF_OP
:
1163 mInScopeGrayOut
= FALSE
;
1167 if (IsExpressionOpCode (ScopeOpCode
)) {