2 Parser for IFR binary encoding.
4 Copyright (c) 2008, 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.
17 #include <Protocol/HiiConfigAccess.h>
18 #include <Protocol/HiiConfigRouting.h>
19 #include <Protocol/HiiDatabase.h>
20 #include <Protocol/HiiString.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/HiiLib.h>
26 #include <Library/MemoryAllocationLib.h>
27 #include <Library/PrintLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
30 #include <Guid/MdeModuleHii.h>
32 #include "UefiIfrParser.h"
34 #include "UefiIfrParserExpression.h"
36 UINT16 mStatementIndex
;
38 BOOLEAN mInScopeSubtitle
;
39 BOOLEAN mInScopeSuppress
;
40 BOOLEAN mInScopeGrayOut
;
42 EFI_GUID mFrameworkHiiCompatibilityGuid
= EFI_IFR_FRAMEWORK_GUID
;
43 extern EFI_GUID mTianoHiiIfrGuid
;
46 GetOneOfOptionMapEntryListHead (
47 IN CONST FORM_BROWSER_FORMSET
*FormSet
,
52 ONE_OF_OPTION_MAP
*Map
;
54 Link
= GetFirstNode (&FormSet
->OneOfOptionMapListHead
);
56 while (!IsNull (&FormSet
->OneOfOptionMapListHead
, Link
)) {
57 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
58 if (QuestionId
== Map
->QuestionId
) {
59 return &Map
->OneOfOptionMapEntryListHead
;
61 Link
= GetNextNode (&FormSet
->OneOfOptionMapListHead
, Link
);
68 DestoryOneOfOptionMap (
69 IN LIST_ENTRY
*OneOfOptionMapListHead
72 ONE_OF_OPTION_MAP
*Map
;
73 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
77 while (!IsListEmpty (OneOfOptionMapListHead
)) {
78 Link
= GetFirstNode (OneOfOptionMapListHead
);
80 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
82 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
83 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
85 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
87 RemoveEntryList (Link2
);
92 RemoveEntryList (Link
);
99 Initialize Statement header members.
101 @param OpCodeData Pointer of the raw OpCode data.
102 @param FormSet Pointer of the current FormSe.
103 @param Form Pointer of the current Form.
105 @return The Statement.
108 FORM_BROWSER_STATEMENT
*
110 IN UINT8
*OpCodeData
,
111 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
112 IN OUT FORM_BROWSER_FORM
*Form
115 FORM_BROWSER_STATEMENT
*Statement
;
116 EFI_IFR_STATEMENT_HEADER
*StatementHdr
;
120 // We are currently not in a Form Scope, so just skip this Statement
125 Statement
= &FormSet
->StatementBuffer
[mStatementIndex
];
128 InitializeListHead (&Statement
->DefaultListHead
);
129 InitializeListHead (&Statement
->OptionListHead
);
131 Statement
->Signature
= FORM_BROWSER_STATEMENT_SIGNATURE
;
133 Statement
->Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
135 StatementHdr
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
136 CopyMem (&Statement
->Prompt
, &StatementHdr
->Prompt
, sizeof (EFI_STRING_ID
));
137 CopyMem (&Statement
->Help
, &StatementHdr
->Help
, sizeof (EFI_STRING_ID
));
139 Statement
->InSubtitle
= mInScopeSubtitle
;
142 // Insert this Statement into current Form
144 InsertTailList (&Form
->StatementListHead
, &Statement
->Link
);
150 Initialize Question's members.
152 @param OpCodeData Pointer of the raw OpCode data.
153 @param FormSet Pointer of the current FormSet.
154 @param Form Pointer of the current Form.
156 @return The Question.
159 FORM_BROWSER_STATEMENT
*
161 IN UINT8
*OpCodeData
,
162 IN OUT FORM_BROWSER_FORMSET
*FormSet
,
163 IN OUT FORM_BROWSER_FORM
*Form
166 FORM_BROWSER_STATEMENT
*Statement
;
167 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
169 FORMSET_STORAGE
*Storage
;
171 Statement
= CreateStatement (OpCodeData
, FormSet
, Form
);
172 if (Statement
== NULL
) {
176 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
177 CopyMem (&Statement
->QuestionId
, &QuestionHdr
->QuestionId
, sizeof (EFI_QUESTION_ID
));
178 CopyMem (&Statement
->VarStoreId
, &QuestionHdr
->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
179 CopyMem (&Statement
->VarStoreInfo
.VarOffset
, &QuestionHdr
->VarStoreInfo
.VarOffset
, sizeof (UINT16
));
181 if (FormSet
->MaxQuestionId
< QuestionHdr
->QuestionId
) {
182 FormSet
->MaxQuestionId
= QuestionHdr
->QuestionId
;
185 Statement
->QuestionFlags
= QuestionHdr
->Flags
;
187 if (Statement
->VarStoreId
== 0) {
189 // VarStoreId of zero indicates no variable storage
195 // Find Storage for this Question
197 Link
= GetFirstNode (&FormSet
->StorageListHead
);
198 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
199 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
201 if (Storage
->VarStoreId
== Statement
->VarStoreId
) {
202 Statement
->Storage
= Storage
;
206 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
208 ASSERT (Statement
->Storage
!= NULL
);
214 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
216 @param FormSet Pointer of the current FormSet
218 @return Pointer to a FORMSET_STORAGE data structure.
223 IN FORM_BROWSER_FORMSET
*FormSet
226 FORMSET_STORAGE
*Storage
;
228 Storage
= AllocateZeroPool (sizeof (FORMSET_STORAGE
));
229 Storage
->Signature
= FORMSET_STORAGE_SIGNATURE
;
230 InsertTailList (&FormSet
->StorageListHead
, &Storage
->Link
);
236 Free resources of a storage
238 @param Storage Pointer of the storage
245 IN FORMSET_STORAGE
*Storage
248 if (Storage
== NULL
) {
252 if (Storage
->Name
!= NULL
) {
253 FreePool (Storage
->Name
);
261 Free resources of a Statement
263 @param Statement Pointer of the Statement
270 IN OUT FORM_BROWSER_STATEMENT
*Statement
274 QUESTION_DEFAULT
*Default
;
275 QUESTION_OPTION
*Option
;
278 // Free Default value List
280 while (!IsListEmpty (&Statement
->DefaultListHead
)) {
281 Link
= GetFirstNode (&Statement
->DefaultListHead
);
282 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
283 RemoveEntryList (&Default
->Link
);
285 gBS
->FreePool (Default
);
291 while (!IsListEmpty (&Statement
->OptionListHead
)) {
292 Link
= GetFirstNode (&Statement
->OptionListHead
);
293 Option
= QUESTION_OPTION_FROM_LINK (Link
);
294 RemoveEntryList (&Option
->Link
);
296 gBS
->FreePool (Option
);
304 Free resources of a Form
306 @param Form Pointer of the Form
313 IN OUT FORM_BROWSER_FORM
*Form
317 FORM_BROWSER_STATEMENT
*Statement
;
320 // Free Statements/Questions
322 while (!IsListEmpty (&Form
->StatementListHead
)) {
323 Link
= GetFirstNode (&Form
->StatementListHead
);
324 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
325 RemoveEntryList (&Statement
->Link
);
327 DestroyStatement (Statement
);
333 gBS
->FreePool (Form
);
338 Free resources allocated for a FormSet
340 @param FormSet Pointer of the FormSet
347 IN OUT FORM_BROWSER_FORMSET
*FormSet
351 FORMSET_STORAGE
*Storage
;
352 FORMSET_DEFAULTSTORE
*DefaultStore
;
353 FORM_BROWSER_FORM
*Form
;
356 // Free IFR binary buffer
358 FreePool (FormSet
->IfrBinaryData
);
361 // Free FormSet Storage
363 if (FormSet
->StorageListHead
.ForwardLink
!= NULL
) {
364 while (!IsListEmpty (&FormSet
->StorageListHead
)) {
365 Link
= GetFirstNode (&FormSet
->StorageListHead
);
366 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
367 RemoveEntryList (&Storage
->Link
);
369 DestroyStorage (Storage
);
374 // Free FormSet Default Store
376 if (FormSet
->DefaultStoreListHead
.ForwardLink
!= NULL
) {
377 while (!IsListEmpty (&FormSet
->DefaultStoreListHead
)) {
378 Link
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
379 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (Link
);
380 RemoveEntryList (&DefaultStore
->Link
);
382 gBS
->FreePool (DefaultStore
);
389 if (FormSet
->FormListHead
.ForwardLink
!= NULL
) {
390 while (!IsListEmpty (&FormSet
->FormListHead
)) {
391 Link
= GetFirstNode (&FormSet
->FormListHead
);
392 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
393 RemoveEntryList (&Form
->Link
);
399 if (FormSet
->StatementBuffer
!= NULL
) {
400 FreePool (FormSet
->StatementBuffer
);
403 DestoryOneOfOptionMap (&FormSet
->OneOfOptionMapListHead
);
405 if (FormSet
->OriginalDefaultVarStoreName
!= NULL
) {
406 FreePool (FormSet
->OriginalDefaultVarStoreName
);
414 Tell whether this Operand is an Expression OpCode or not
416 @param Operand Operand of an IFR OpCode.
418 @retval TRUE This is an Expression OpCode.
419 @retval FALSE Not an Expression OpCode.
427 if (((Operand
>= EFI_IFR_EQ_ID_VAL_OP
) && (Operand
<= EFI_IFR_NOT_OP
)) ||
428 ((Operand
>= EFI_IFR_MATCH_OP
) && (Operand
<= EFI_IFR_SPAN_OP
)) ||
429 (Operand
== EFI_IFR_CATENATE_OP
)
439 Calculate number of Statemens(Questions) and Expression OpCodes.
441 @param FormSet The FormSet to be counted.
442 @param NumberOfStatement Number of Statemens(Questions)
443 @param NumberOfExpression Number of Expression OpCodes
450 IN FORM_BROWSER_FORMSET
*FormSet
,
451 IN OUT UINT16
*NumberOfStatement
,
452 IN OUT UINT16
*NumberOfExpression
455 UINT16 StatementCount
;
456 UINT16 ExpressionCount
;
465 while (Offset
< FormSet
->IfrBinaryLength
) {
466 OpCodeData
= FormSet
->IfrBinaryData
+ Offset
;
467 OpCodeLen
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
470 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
)) {
477 *NumberOfStatement
= StatementCount
;
478 *NumberOfExpression
= ExpressionCount
;
483 Parse opcodes in the formset IFR binary.
485 @param FormSet Pointer of the FormSet data structure.
487 @retval EFI_SUCCESS Opcode parse success.
488 @retval Other Opcode parse fail.
493 IN FORM_BROWSER_FORMSET
*FormSet
498 FORM_BROWSER_FORM
*CurrentForm
;
499 FORM_BROWSER_STATEMENT
*CurrentStatement
;
506 FORMSET_STORAGE
*Storage
;
507 FORMSET_DEFAULTSTORE
*DefaultStore
;
508 QUESTION_DEFAULT
*CurrentDefault
;
509 QUESTION_OPTION
*CurrentOption
;
511 UINT16 NumberOfStatement
;
512 UINT16 NumberOfExpression
;
513 EFI_IMAGE_ID
*ImageId
;
514 EFI_HII_VALUE
*Value
;
515 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
516 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
517 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
518 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
520 EFI_IFR_ONE_OF
*OneOfOpcode
;
522 mInScopeSubtitle
= FALSE
;
523 mInScopeSuppress
= FALSE
;
524 mInScopeGrayOut
= FALSE
;
525 CurrentDefault
= NULL
;
526 CurrentOption
= NULL
;
529 // Set to a invalid value.
531 OneOfType
= (UINT8
) -1;
534 // Get the number of Statements and Expressions
536 CountOpCodes (FormSet
, &NumberOfStatement
, &NumberOfExpression
);
537 FormSet
->NumberOfStatement
= NumberOfStatement
;
540 FormSet
->StatementBuffer
= AllocateZeroPool (NumberOfStatement
* sizeof (FORM_BROWSER_STATEMENT
));
541 if (FormSet
->StatementBuffer
== NULL
) {
542 return EFI_OUT_OF_RESOURCES
;
545 InitializeListHead (&FormSet
->StorageListHead
);
546 InitializeListHead (&FormSet
->DefaultStoreListHead
);
547 InitializeListHead (&FormSet
->FormListHead
);
548 InitializeListHead (&FormSet
->OneOfOptionMapListHead
);
551 CurrentStatement
= NULL
;
556 while (OpCodeOffset
< FormSet
->IfrBinaryLength
) {
557 OpCodeData
= FormSet
->IfrBinaryData
+ OpCodeOffset
;
559 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
560 OpCodeOffset
+= OpCodeLength
;
561 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
562 Scope
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Scope
;
565 // If scope bit set, push onto scope stack
571 if (IsExpressionOpCode (Operand
)) {
580 case EFI_IFR_FORM_SET_OP
:
582 // check the formset GUID
584 if (!CompareGuid ((EFI_GUID
*)(VOID
*)&FormSet
->Guid
, (EFI_GUID
*)(VOID
*)&((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
)) {
585 return EFI_INVALID_PARAMETER
;
588 CopyMem (&FormSet
->FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
589 CopyMem (&FormSet
->Help
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
592 case EFI_IFR_FORM_OP
:
594 // Create a new Form for this FormSet
596 CurrentForm
= AllocateZeroPool (sizeof (FORM_BROWSER_FORM
));
597 CurrentForm
->Signature
= FORM_BROWSER_FORM_SIGNATURE
;
599 InitializeListHead (&CurrentForm
->StatementListHead
);
601 CopyMem (&CurrentForm
->FormId
, &((EFI_IFR_FORM
*) OpCodeData
)->FormId
, sizeof (UINT16
));
602 CopyMem (&CurrentForm
->FormTitle
, &((EFI_IFR_FORM
*) OpCodeData
)->FormTitle
, sizeof (EFI_STRING_ID
));
605 // Insert into Form list of this FormSet
607 InsertTailList (&FormSet
->FormListHead
, &CurrentForm
->Link
);
613 case EFI_IFR_VARSTORE_OP
:
615 // Create a buffer Storage for this FormSet
617 Storage
= CreateStorage (FormSet
);
618 Storage
->Type
= EFI_HII_VARSTORE_BUFFER
;
620 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
621 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
622 CopyMem (&Storage
->Size
, &((EFI_IFR_VARSTORE
*) OpCodeData
)->Size
, sizeof (UINT16
));
624 AsciiString
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
625 Storage
->Name
= AllocateZeroPool (AsciiStrSize (AsciiString
) * 2);
626 ASSERT (Storage
->Name
!= NULL
);
627 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
628 Storage
->Name
[Index
] = (CHAR16
) AsciiString
[Index
];
633 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
638 case EFI_IFR_VARSTORE_EFI_OP
:
640 // Create a EFI variable Storage for this FormSet
642 Storage
= CreateStorage (FormSet
);
643 Storage
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE
;
645 CopyMem (&Storage
->VarStoreId
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
, sizeof (EFI_VARSTORE_ID
));
646 CopyMem (&Storage
->Guid
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
647 CopyMem (&Storage
->Attributes
, &((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Attributes
, sizeof (UINT32
));
653 case EFI_IFR_DEFAULTSTORE_OP
:
654 DefaultStore
= AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE
));
655 DefaultStore
->Signature
= FORMSET_DEFAULTSTORE_SIGNATURE
;
657 CopyMem (&DefaultStore
->DefaultId
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
658 CopyMem (&DefaultStore
->DefaultName
, &((EFI_IFR_DEFAULTSTORE
*) OpCodeData
)->DefaultName
, sizeof (EFI_STRING_ID
));
661 // Insert to DefaultStore list of this Formset
663 InsertTailList (&FormSet
->DefaultStoreListHead
, &DefaultStore
->Link
);
669 case EFI_IFR_SUBTITLE_OP
:
670 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
671 CurrentStatement
->Flags
= ((EFI_IFR_SUBTITLE
*) OpCodeData
)->Flags
;
674 mInScopeSubtitle
= TRUE
;
678 case EFI_IFR_TEXT_OP
:
679 CurrentStatement
= CreateStatement (OpCodeData
, FormSet
, CurrentForm
);
681 CopyMem (&CurrentStatement
->TextTwo
, &((EFI_IFR_TEXT
*) OpCodeData
)->TextTwo
, sizeof (EFI_STRING_ID
));
687 case EFI_IFR_ACTION_OP
:
688 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
690 if (OpCodeLength
== sizeof (EFI_IFR_ACTION_1
)) {
692 // No QuestionConfig present, so no configuration string will be processed
694 CurrentStatement
->QuestionConfig
= 0;
696 CopyMem (&CurrentStatement
->QuestionConfig
, &((EFI_IFR_ACTION
*) OpCodeData
)->QuestionConfig
, sizeof (EFI_STRING_ID
));
700 case EFI_IFR_RESET_BUTTON_OP
:
701 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
703 CopyMem (&CurrentStatement
->DefaultId
, &((EFI_IFR_RESET_BUTTON
*) OpCodeData
)->DefaultId
, sizeof (EFI_DEFAULT_ID
));
707 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
709 CopyMem (&CurrentStatement
->RefFormId
, &((EFI_IFR_REF
*) OpCodeData
)->FormId
, sizeof (EFI_FORM_ID
));
710 if (OpCodeLength
>= sizeof (EFI_IFR_REF2
)) {
711 CopyMem (&CurrentStatement
->RefQuestionId
, &((EFI_IFR_REF2
*) OpCodeData
)->QuestionId
, sizeof (EFI_QUESTION_ID
));
713 if (OpCodeLength
>= sizeof (EFI_IFR_REF3
)) {
714 CopyMem (&CurrentStatement
->RefFormSetId
, &((EFI_IFR_REF3
*) OpCodeData
)->FormSetId
, sizeof (EFI_GUID
));
716 if (OpCodeLength
>= sizeof (EFI_IFR_REF4
)) {
717 CopyMem (&CurrentStatement
->RefDevicePath
, &((EFI_IFR_REF4
*) OpCodeData
)->DevicePath
, sizeof (EFI_STRING_ID
));
723 case EFI_IFR_ONE_OF_OP
:
724 case EFI_IFR_NUMERIC_OP
:
725 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
727 CurrentStatement
->Flags
= ((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
;
728 Value
= &CurrentStatement
->HiiValue
;
730 switch (CurrentStatement
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
731 case EFI_IFR_NUMERIC_SIZE_1
:
732 CurrentStatement
->Minimum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MinValue
;
733 CurrentStatement
->Maximum
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.MaxValue
;
734 CurrentStatement
->Step
= ((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u8
.Step
;
735 CurrentStatement
->StorageWidth
= sizeof (UINT8
);
736 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
739 case EFI_IFR_NUMERIC_SIZE_2
:
740 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MinValue
, sizeof (UINT16
));
741 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.MaxValue
, sizeof (UINT16
));
742 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u16
.Step
, sizeof (UINT16
));
743 CurrentStatement
->StorageWidth
= sizeof (UINT16
);
744 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
747 case EFI_IFR_NUMERIC_SIZE_4
:
748 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MinValue
, sizeof (UINT32
));
749 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.MaxValue
, sizeof (UINT32
));
750 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u32
.Step
, sizeof (UINT32
));
751 CurrentStatement
->StorageWidth
= sizeof (UINT32
);
752 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_32
;
755 case EFI_IFR_NUMERIC_SIZE_8
:
756 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MinValue
, sizeof (UINT64
));
757 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.MaxValue
, sizeof (UINT64
));
758 CopyMem (&CurrentStatement
->Step
, &((EFI_IFR_NUMERIC
*) OpCodeData
)->data
.u64
.Step
, sizeof (UINT64
));
759 CurrentStatement
->StorageWidth
= sizeof (UINT64
);
760 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
767 if (Operand
== EFI_IFR_ONE_OF_OP
) {
768 OneOfOpcode
= (EFI_IFR_ONE_OF
*) OpCodeData
;
769 OneOfType
= (UINT8
) (OneOfOpcode
->Flags
& EFI_IFR_NUMERIC_SIZE
);
773 case EFI_IFR_ORDERED_LIST_OP
:
774 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
776 CurrentStatement
->Flags
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Flags
;
777 CurrentStatement
->MaxContainers
= ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
778 CurrentStatement
->StorageWidth
= (UINT16
)(CurrentStatement
->MaxContainers
* sizeof (UINT8
));
781 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
782 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
783 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
785 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_OTHER
;
786 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
790 case EFI_IFR_CHECKBOX_OP
:
791 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
793 CurrentStatement
->Flags
= ((EFI_IFR_CHECKBOX
*) OpCodeData
)->Flags
;
794 CurrentStatement
->StorageWidth
= sizeof (BOOLEAN
);
795 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_BOOLEAN
;
799 case EFI_IFR_STRING_OP
:
800 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
803 // MinSize is the minimum number of characters that can be accepted for this opcode,
804 // MaxSize is the maximum number of characters that can be accepted for this opcode.
805 // The characters are stored as Unicode, so the storage width should multiply 2.
807 CurrentStatement
->Minimum
= ((EFI_IFR_STRING
*) OpCodeData
)->MinSize
;
808 CurrentStatement
->Maximum
= ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
;
809 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
810 CurrentStatement
->Flags
= ((EFI_IFR_STRING
*) OpCodeData
)->Flags
;
812 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
813 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
817 case EFI_IFR_PASSWORD_OP
:
818 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
821 // MinSize is the minimum number of characters that can be accepted for this opcode,
822 // MaxSize is the maximum number of characters that can be accepted for this opcode.
823 // The characters are stored as Unicode, so the storage width should multiply 2.
825 CopyMem (&CurrentStatement
->Minimum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MinSize
, sizeof (UINT16
));
826 CopyMem (&CurrentStatement
->Maximum
, &((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
, sizeof (UINT16
));
827 CurrentStatement
->StorageWidth
= (UINT16
)((UINTN
) CurrentStatement
->Maximum
* sizeof (UINT16
));
829 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_STRING
;
830 CurrentStatement
->BufferValue
= AllocateZeroPool (CurrentStatement
->StorageWidth
);
834 case EFI_IFR_DATE_OP
:
835 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
837 CurrentStatement
->Flags
= ((EFI_IFR_DATE
*) OpCodeData
)->Flags
;
838 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_DATE
;
842 case EFI_IFR_TIME_OP
:
843 CurrentStatement
= CreateQuestion (OpCodeData
, FormSet
, CurrentForm
);
845 CurrentStatement
->Flags
= ((EFI_IFR_TIME
*) OpCodeData
)->Flags
;
846 CurrentStatement
->HiiValue
.Type
= EFI_IFR_TYPE_TIME
;
853 case EFI_IFR_DEFAULT_OP
:
855 // EFI_IFR_DEFAULT appear in scope of a Question,
856 // It creates a default value for the current question.
857 // A Question may have more than one Default value which have different default types.
859 CurrentDefault
= AllocateZeroPool (sizeof (QUESTION_DEFAULT
));
860 CurrentDefault
->Signature
= QUESTION_DEFAULT_SIGNATURE
;
862 CurrentDefault
->Value
.Type
= ((EFI_IFR_DEFAULT
*) OpCodeData
)->Type
;
863 CopyMem (&CurrentDefault
->DefaultId
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->DefaultId
, sizeof (UINT16
));
864 CopyMem (&CurrentDefault
->Value
.Value
, &((EFI_IFR_DEFAULT
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
865 ExtendValueToU64 (&CurrentDefault
->Value
);
868 // Insert to Default Value list of current Question
870 InsertTailList (&CurrentStatement
->DefaultListHead
, &CurrentDefault
->Link
);
877 case EFI_IFR_ONE_OF_OPTION_OP
:
879 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
880 // It create a selection for use in current Question.
882 CurrentOption
= AllocateZeroPool (sizeof (QUESTION_OPTION
));
883 CurrentOption
->Signature
= QUESTION_OPTION_SIGNATURE
;
885 CurrentOption
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Flags
;
886 CurrentOption
->Value
.Type
= ((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Type
;
887 CopyMem (&CurrentOption
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Option
, sizeof (EFI_STRING_ID
));
888 CopyMem (&CurrentOption
->Value
.Value
, &((EFI_IFR_ONE_OF_OPTION
*) OpCodeData
)->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
889 ExtendValueToU64 (&CurrentOption
->Value
);
892 // Insert to Option list of current Question
894 InsertTailList (&CurrentStatement
->OptionListHead
, &CurrentOption
->Link
);
900 case EFI_IFR_NO_SUBMIT_IF_OP
:
901 case EFI_IFR_INCONSISTENT_IF_OP
:
904 case EFI_IFR_SUPPRESS_IF_OP
:
907 case EFI_IFR_GRAY_OUT_IF_OP
:
910 case EFI_IFR_DISABLE_IF_OP
:
917 case EFI_IFR_VALUE_OP
:
920 case EFI_IFR_RULE_OP
:
926 case EFI_IFR_IMAGE_OP
:
928 // Get ScopeOpcode from top of stack
930 PopScope (&ScopeOpCode
);
931 PushScope (ScopeOpCode
);
933 switch (ScopeOpCode
) {
934 case EFI_IFR_FORM_SET_OP
:
935 ImageId
= &FormSet
->ImageId
;
938 case EFI_IFR_FORM_OP
:
939 ImageId
= &CurrentForm
->ImageId
;
942 case EFI_IFR_ONE_OF_OPTION_OP
:
943 ImageId
= &CurrentOption
->ImageId
;
947 ImageId
= &CurrentStatement
->ImageId
;
951 CopyMem (ImageId
, &((EFI_IFR_IMAGE
*) OpCodeData
)->Id
, sizeof (EFI_IMAGE_ID
));
957 case EFI_IFR_REFRESH_OP
:
958 CurrentStatement
->RefreshInterval
= ((EFI_IFR_REFRESH
*) OpCodeData
)->RefreshInterval
;
964 case EFI_IFR_GUID_OP
:
965 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCodeData
;
967 if (CompareGuid (&mTianoHiiIfrGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
969 // Tiano specific GUIDed opcodes
971 switch (((EFI_IFR_GUID_LABEL
*) OpCodeData
)->ExtendOpCode
) {
972 case EFI_IFR_EXTEND_OP_LABEL
:
979 case EFI_IFR_EXTEND_OP_CLASS
:
980 CopyMem (&FormSet
->Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
983 case EFI_IFR_EXTEND_OP_SUBCLASS
:
984 CopyMem (&FormSet
->SubClass
, &((EFI_IFR_GUID_SUBCLASS
*) OpCodeData
)->SubClass
, sizeof (UINT16
));
991 else if (CompareGuid ((EFI_GUID
*)(VOID
*)&OptionMap
->Guid
, &mFrameworkHiiCompatibilityGuid
)) {
992 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
993 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (FormSet
, OptionMap
->QuestionId
);
994 if (OneOfOptinMapEntryListHead
== NULL
) {
995 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
996 ASSERT (OneOfOptionMap
!= NULL
);
998 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
999 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
1002 // Make sure OneOfType is initialized.
1004 ASSERT (OneOfType
!= (UINT8
) -1);
1005 OneOfOptionMap
->ValueType
= OneOfType
;
1006 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
1007 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
1008 InsertTailList (&FormSet
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
1010 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
1011 ASSERT (OneOfOptionMapEntry
!= NULL
);
1013 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
1014 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
1015 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
1017 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
1025 case EFI_IFR_END_OP
:
1026 Status
= PopScope (&ScopeOpCode
);
1027 if (EFI_ERROR (Status
)) {
1032 switch (ScopeOpCode
) {
1033 case EFI_IFR_FORM_SET_OP
:
1035 // End of FormSet, update FormSet IFR binary length
1036 // to stop parsing substantial OpCodes
1038 FormSet
->IfrBinaryLength
= OpCodeOffset
;
1041 case EFI_IFR_FORM_OP
:
1048 case EFI_IFR_ONE_OF_OPTION_OP
:
1052 CurrentOption
= NULL
;
1055 case EFI_IFR_SUBTITLE_OP
:
1056 mInScopeSubtitle
= FALSE
;
1059 case EFI_IFR_NO_SUBMIT_IF_OP
:
1060 case EFI_IFR_INCONSISTENT_IF_OP
:
1062 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1066 case EFI_IFR_GRAY_OUT_IF_OP
:
1067 mInScopeGrayOut
= FALSE
;
1071 if (IsExpressionOpCode (ScopeOpCode
)) {