2 Utility functions for UI presentation.
4 Copyright (c) 2004 - 2015, 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.
17 BOOLEAN mHiiPackageListUpdated
;
18 UI_MENU_SELECTION
*gCurrentSelection
;
19 EFI_HII_HANDLE mCurrentHiiHandle
= NULL
;
20 EFI_GUID mCurrentFormSetGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
21 UINT16 mCurrentFormId
= 0;
22 EFI_EVENT mValueChangedEvent
= NULL
;
23 LIST_ENTRY mRefreshEventList
= INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList
);
24 UINT16 mCurFakeQestId
;
25 FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
26 BOOLEAN mFinishRetrieveCall
= FALSE
;
29 Evaluate all expressions in a Form.
31 @param FormSet FormSet this Form belongs to.
34 @retval EFI_SUCCESS The expression evaluated successfuly
38 EvaluateFormExpressions (
39 IN FORM_BROWSER_FORMSET
*FormSet
,
40 IN FORM_BROWSER_FORM
*Form
45 FORM_EXPRESSION
*Expression
;
47 Link
= GetFirstNode (&Form
->ExpressionListHead
);
48 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
49 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
50 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
52 if (Expression
->Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
||
53 Expression
->Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
||
54 Expression
->Type
== EFI_HII_EXPRESSION_WARNING_IF
||
55 Expression
->Type
== EFI_HII_EXPRESSION_WRITE
||
56 (Expression
->Type
== EFI_HII_EXPRESSION_READ
&& Form
->FormType
!= STANDARD_MAP_FORM_TYPE
)) {
58 // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
63 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
64 if (EFI_ERROR (Status
)) {
73 Add empty function for event process function.
75 @param Event The Event need to be process
76 @param Context The context of the event.
81 SetupBrowserEmptyFunction (
89 Base on the opcode buffer info to get the display statement.
91 @param OpCode The input opcode buffer for this statement.
93 @retval Statement The statement use this opcode buffer.
96 FORM_DISPLAY_ENGINE_STATEMENT
*
98 IN EFI_IFR_OP_HEADER
*OpCode
101 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
104 Link
= GetFirstNode (&gDisplayFormData
.StatementListHead
);
105 while (!IsNull (&gDisplayFormData
.StatementListHead
, Link
)) {
106 DisplayStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
108 if (DisplayStatement
->OpCode
== OpCode
) {
109 return DisplayStatement
;
111 Link
= GetNextNode (&gDisplayFormData
.StatementListHead
, Link
);
118 Free the refresh event list.
127 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
129 while (!IsListEmpty (&mRefreshEventList
)) {
130 Link
= GetFirstNode (&mRefreshEventList
);
131 EventNode
= FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link
);
132 RemoveEntryList (&EventNode
->Link
);
134 gBS
->CloseEvent (EventNode
->RefreshEvent
);
136 FreePool (EventNode
);
141 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
144 @param Statement The statement need to check.
149 IN OUT FORM_BROWSER_STATEMENT
*Statement
152 GetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
155 // Reset FormPackage update flag
157 mHiiPackageListUpdated
= FALSE
;
160 // Question value may be changed, need invoke its Callback()
162 ProcessCallBackFunction (gCurrentSelection
, gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
164 if (mHiiPackageListUpdated
) {
166 // Package list is updated, force to reparse IFR binary of target Formset
168 mHiiPackageListUpdated
= FALSE
;
169 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
174 Refresh the question which has refresh guid event attribute.
176 @param Event The event which has this function related.
177 @param Context The input context info related to this event or the status code return to the caller.
181 RefreshEventNotifyForStatement(
186 FORM_BROWSER_STATEMENT
*Statement
;
188 Statement
= (FORM_BROWSER_STATEMENT
*)Context
;
189 UpdateStatement(Statement
);
190 gBS
->SignalEvent (mValueChangedEvent
);
194 Refresh the questions within this form.
196 @param Event The event which has this function related.
197 @param Context The input context info related to this event or the status code return to the caller.
201 RefreshEventNotifyForForm(
206 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
208 gBS
->SignalEvent (mValueChangedEvent
);
212 Create refresh hook event for statement which has refresh event or interval.
214 @param Statement The statement need to check.
218 CreateRefreshEventForStatement (
219 IN FORM_BROWSER_STATEMENT
*Statement
223 EFI_EVENT RefreshEvent
;
224 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
227 // If question has refresh guid, create the notify function.
229 Status
= gBS
->CreateEventEx (
232 RefreshEventNotifyForStatement
,
234 &Statement
->RefreshGuid
,
236 ASSERT_EFI_ERROR (Status
);
238 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
239 ASSERT (EventNode
!= NULL
);
240 EventNode
->RefreshEvent
= RefreshEvent
;
241 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
245 Create refresh hook event for form which has refresh event or interval.
247 @param Form The form need to check.
251 CreateRefreshEventForForm (
252 IN FORM_BROWSER_FORM
*Form
256 EFI_EVENT RefreshEvent
;
257 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
260 // If question has refresh guid, create the notify function.
262 Status
= gBS
->CreateEventEx (
265 RefreshEventNotifyForForm
,
269 ASSERT_EFI_ERROR (Status
);
271 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
272 ASSERT (EventNode
!= NULL
);
273 EventNode
->RefreshEvent
= RefreshEvent
;
274 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
279 Initialize the Display statement structure data.
281 @param DisplayStatement Pointer to the display Statement data strucure.
282 @param Statement The statement need to check.
285 InitializeDisplayStatement (
286 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
287 IN FORM_BROWSER_STATEMENT
*Statement
291 QUESTION_OPTION
*Option
;
292 DISPLAY_QUESTION_OPTION
*DisplayOption
;
293 FORM_DISPLAY_ENGINE_STATEMENT
*ParentStatement
;
295 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
296 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
297 DisplayStatement
->OpCode
= Statement
->OpCode
;
298 InitializeListHead (&DisplayStatement
->NestStatementList
);
299 InitializeListHead (&DisplayStatement
->OptionListHead
);
301 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
302 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
304 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
305 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
309 // Initilize the option list in statement.
311 Link
= GetFirstNode (&Statement
->OptionListHead
);
312 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
313 Option
= QUESTION_OPTION_FROM_LINK (Link
);
314 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
315 if ((Option
->SuppressExpression
!= NULL
) &&
316 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
320 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
321 ASSERT (DisplayOption
!= NULL
);
323 DisplayOption
->ImageId
= Option
->ImageId
;
324 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
325 DisplayOption
->OptionOpCode
= Option
->OpCode
;
326 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
329 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
332 // Some special op code need an extra buffer to save the data.
333 // Such as string, password, orderedlist...
335 if (Statement
->BufferValue
!= NULL
) {
337 // Ordered list opcode may not initilized, get default value here.
339 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
340 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
343 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
344 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
347 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
350 // Get the highlight statement for current form.
352 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
353 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
354 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
358 // Create the refresh event process function.
360 if (!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) {
361 CreateRefreshEventForStatement (Statement
);
365 // For RTC type of date/time, set default refresh interval to be 1 second.
367 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
368 Statement
->RefreshInterval
= 1;
372 // Create the refresh guid hook event.
373 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
375 if ((!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) || (Statement
->RefreshInterval
!= 0)) {
376 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
380 // Save the password check function for later use.
382 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
383 DisplayStatement
->PasswordCheck
= PasswordCheck
;
387 // If this statement is nest in the subtitle, insert to the host statement.
388 // else insert to the form it belongs to.
390 if (Statement
->ParentStatement
!= NULL
) {
391 ParentStatement
= GetDisplayStatement(Statement
->ParentStatement
->OpCode
);
392 ASSERT (ParentStatement
!= NULL
);
393 InsertTailList(&ParentStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
395 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
400 Process for the refresh interval statement.
402 @param Event The Event need to be process
403 @param Context The context of the event.
408 RefreshIntervalProcess (
413 FORM_BROWSER_STATEMENT
*Statement
;
416 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
417 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
418 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
419 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
421 if (Statement
->RefreshInterval
== 0) {
425 UpdateStatement(Statement
);
428 gBS
->SignalEvent (mValueChangedEvent
);
433 Make a copy of the global hotkey info.
441 BROWSER_HOT_KEY
*HotKey
;
442 BROWSER_HOT_KEY
*CopyKey
;
445 Link
= GetFirstNode (&gBrowserHotKeyList
);
446 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
447 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
449 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
450 ASSERT (CopyKey
!= NULL
);
451 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
452 ASSERT (CopyKey
->KeyData
!= NULL
);
453 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
454 ASSERT (CopyKey
->HelpString
!= NULL
);
456 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
458 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
464 Get the extra question attribute from override question list.
466 @param QuestionId The question id for this request question.
468 @retval The attribute for this question or NULL if not found this
469 question in the list.
473 ProcessQuestionExtraAttr (
474 IN EFI_QUESTION_ID QuestionId
478 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
481 // Return HII_DISPLAY_NONE if input a invalid question id.
483 if (QuestionId
== 0) {
484 return HII_DISPLAY_NONE
;
487 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
488 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
489 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
490 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
492 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
493 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
494 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
495 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
496 return QuestionDesc
->Attribute
;
500 return HII_DISPLAY_NONE
;
505 Enum all statement in current form, find all the statement can be display and
506 add to the display form.
510 AddStatementToDisplayForm (
516 FORM_BROWSER_STATEMENT
*Statement
;
517 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
518 UINT8 MinRefreshInterval
;
519 EFI_EVENT RefreshIntervalEvent
;
520 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
521 BOOLEAN FormEditable
;
522 UINT32 ExtraAttribute
;
524 MinRefreshInterval
= 0;
525 FormEditable
= FALSE
;
528 // Process the statement outside the form, these statements are not recognized
531 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
532 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
533 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
534 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
536 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
537 ASSERT (DisplayStatement
!= NULL
);
538 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
539 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
540 DisplayStatement
->OpCode
= Statement
->OpCode
;
542 InitializeListHead (&DisplayStatement
->NestStatementList
);
543 InitializeListHead (&DisplayStatement
->OptionListHead
);
545 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
549 // Process the statement in this form.
551 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
552 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
553 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
554 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
557 // This statement can't be show, skip it.
559 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
564 // Check the extra attribute.
566 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
567 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
571 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
572 ASSERT (DisplayStatement
!= NULL
);
575 // Initialize this statement and add it to the display form.
577 InitializeDisplayStatement(DisplayStatement
, Statement
);
580 // Set the extra attribute.
582 DisplayStatement
->Attribute
|= ExtraAttribute
;
584 if (Statement
->Storage
!= NULL
) {
589 // Get the minimal refresh interval value for later use.
591 if ((Statement
->RefreshInterval
!= 0) &&
592 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
593 MinRefreshInterval
= Statement
->RefreshInterval
;
598 // Create the periodic timer for refresh interval statement.
600 if (MinRefreshInterval
!= 0) {
601 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
602 ASSERT_EFI_ERROR (Status
);
603 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
604 ASSERT_EFI_ERROR (Status
);
606 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
607 ASSERT (EventNode
!= NULL
);
608 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
609 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
613 // Create the refresh event process function for Form.
615 if (!CompareGuid (&gCurrentSelection
->Form
->RefreshGuid
, &gZeroGuid
)) {
616 CreateRefreshEventForForm (gCurrentSelection
->Form
);
617 if (gDisplayFormData
.FormRefreshEvent
== NULL
) {
618 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
623 // Update hotkey list field.
625 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
632 Initialize the SettingChangedFlag variable in the display form.
636 UpdateDataChangedFlag (
641 FORM_BROWSER_FORMSET
*LocalFormSet
;
643 gDisplayFormData
.SettingChangedFlag
= FALSE
;
645 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
646 gDisplayFormData
.SettingChangedFlag
= TRUE
;
651 // Base on the system level to check whether need to show the NV flag.
653 switch (gBrowserSettingScope
) {
656 // Check the maintain list to see whether there is any change.
658 Link
= GetFirstNode (&gBrowserFormSetList
);
659 while (!IsNull (&gBrowserFormSetList
, Link
)) {
660 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
661 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
662 gDisplayFormData
.SettingChangedFlag
= TRUE
;
665 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
670 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
671 gDisplayFormData
.SettingChangedFlag
= TRUE
;
683 Initialize the Display form structure data.
687 InitializeDisplayFormData (
693 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
694 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
695 gDisplayFormData
.ImageId
= 0;
696 gDisplayFormData
.AnimationId
= 0;
698 InitializeListHead (&gDisplayFormData
.StatementListHead
);
699 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
700 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
702 Status
= gBS
->CreateEvent (
705 SetupBrowserEmptyFunction
,
709 ASSERT_EFI_ERROR (Status
);
714 Free the kotkey info saved in form data.
722 BROWSER_HOT_KEY
*HotKey
;
725 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
726 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
727 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
729 RemoveEntryList (&HotKey
->Link
);
731 FreePool (HotKey
->KeyData
);
732 FreePool (HotKey
->HelpString
);
739 Update the Display form structure data.
743 UpdateDisplayFormData (
747 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
748 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
749 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
750 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
752 gDisplayFormData
.Attribute
= 0;
753 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
754 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
756 gDisplayFormData
.FormRefreshEvent
= NULL
;
757 gDisplayFormData
.HighLightedStatement
= NULL
;
759 UpdateDataChangedFlag ();
761 AddStatementToDisplayForm ();
766 Free the Display Statement structure data.
768 @param StatementList Point to the statement list which need to be free.
773 LIST_ENTRY
*StatementList
777 LIST_ENTRY
*OptionLink
;
778 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
779 DISPLAY_QUESTION_OPTION
*Option
;
782 // Free Statements/Questions
784 while (!IsListEmpty (StatementList
)) {
785 Link
= GetFirstNode (StatementList
);
786 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
791 while (!IsListEmpty (&Statement
->OptionListHead
)) {
792 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
793 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
794 RemoveEntryList (&Option
->Link
);
799 // Free nest statement List
801 if (!IsListEmpty (&Statement
->NestStatementList
)) {
802 FreeStatementData(&Statement
->NestStatementList
);
805 RemoveEntryList (&Statement
->DisplayLink
);
806 FreePool (Statement
);
812 Free the Display form structure data.
816 FreeDisplayFormData (
820 FreeStatementData (&gDisplayFormData
.StatementListHead
);
821 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
830 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
832 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
834 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
837 FORM_BROWSER_STATEMENT
*
838 GetBrowserStatement (
839 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
842 FORM_BROWSER_STATEMENT
*Statement
;
845 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
846 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
847 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
849 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
853 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
860 Update the ValueChanged status for questions in this form.
862 @param FormSet FormSet data structure.
863 @param Form Form data structure.
867 UpdateStatementStatusForForm (
868 IN FORM_BROWSER_FORMSET
*FormSet
,
869 IN FORM_BROWSER_FORM
*Form
873 FORM_BROWSER_STATEMENT
*Question
;
875 Link
= GetFirstNode (&Form
->StatementListHead
);
876 while (!IsNull (&Form
->StatementListHead
, Link
)) {
877 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
878 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
881 // For password opcode, not set the the value changed flag.
883 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
887 IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
892 Update the ValueChanged status for questions in this formset.
894 @param FormSet FormSet data structure.
898 UpdateStatementStatusForFormSet (
899 IN FORM_BROWSER_FORMSET
*FormSet
903 FORM_BROWSER_FORM
*Form
;
905 Link
= GetFirstNode (&FormSet
->FormListHead
);
906 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
907 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
908 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
910 UpdateStatementStatusForForm (FormSet
, Form
);
915 Update the ValueChanged status for questions.
917 @param FormSet FormSet data structure.
918 @param Form Form data structure.
919 @param SettingScope Setting Scope for Default action.
923 UpdateStatementStatus (
924 IN FORM_BROWSER_FORMSET
*FormSet
,
925 IN FORM_BROWSER_FORM
*Form
,
926 IN BROWSER_SETTING_SCOPE SettingScope
930 FORM_BROWSER_FORMSET
*LocalFormSet
;
932 switch (SettingScope
) {
934 Link
= GetFirstNode (&gBrowserFormSetList
);
935 while (!IsNull (&gBrowserFormSetList
, Link
)) {
936 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
937 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
938 if (!ValidateFormSet(LocalFormSet
)) {
942 UpdateStatementStatusForFormSet (LocalFormSet
);
947 UpdateStatementStatusForFormSet (FormSet
);
951 UpdateStatementStatusForForm (FormSet
, Form
);
961 Process the action request in user input.
963 @param Action The user input action request info.
964 @param DefaultId The user input default Id info.
966 @retval EFI_SUCESSS This function always return successfully for now.
976 // This is caused by use press ESC, and it should not combine with other action type.
978 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
979 FindNextMenu (gCurrentSelection
, FormLevel
);
984 // Below is normal hotkey trigged action, these action maybe combine with each other.
986 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
987 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
990 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
991 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
992 UpdateStatementStatus (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
995 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
996 SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
999 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1000 gResetRequired
= TRUE
;
1003 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1005 // Form Exit without saving, Similar to ESC Key.
1006 // FormSet Exit without saving, Exit SendForm.
1007 // System Exit without saving, CallExitHandler and Exit SendForm.
1009 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1010 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1011 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1012 } else if (gBrowserSettingScope
== SystemLevel
) {
1013 if (ExitHandlerFunction
!= NULL
) {
1014 ExitHandlerFunction ();
1016 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1024 Check whether the formset guid is in this Hii package list.
1026 @param HiiHandle The HiiHandle for this HII package list.
1027 @param FormSetGuid The formset guid for the request formset.
1029 @retval TRUE Find the formset guid.
1030 @retval FALSE Not found the formset guid.
1034 GetFormsetGuidFromHiiHandle (
1035 IN EFI_HII_HANDLE HiiHandle
,
1036 IN EFI_GUID
*FormSetGuid
1039 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1043 UINT32 PackageListLength
;
1044 EFI_HII_PACKAGE_HEADER PackageHeader
;
1051 HiiPackageList
= NULL
;
1054 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1055 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1056 HiiPackageList
= AllocatePool (BufferSize
);
1057 ASSERT (HiiPackageList
!= NULL
);
1059 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1061 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1066 // Get Form package from this HII package List
1068 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1070 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1072 while (Offset
< PackageListLength
) {
1073 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1074 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1075 Offset
+= PackageHeader
.Length
;
1077 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1079 // Search FormSet in this Form Package
1081 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1082 while (Offset2
< PackageHeader
.Length
) {
1083 OpCodeData
= Package
+ Offset2
;
1085 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1086 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1092 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1100 FreePool (HiiPackageList
);
1106 Find HII Handle in the HII database associated with given Device Path.
1108 If DevicePath is NULL, then ASSERT.
1110 @param DevicePath Device Path associated with the HII package list
1112 @param FormsetGuid The formset guid for this formset.
1114 @retval Handle HII package list Handle associated with the Device
1116 @retval NULL Hii Package list handle is not found.
1120 DevicePathToHiiHandle (
1121 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1122 IN EFI_GUID
*FormsetGuid
1126 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1129 EFI_HANDLE DriverHandle
;
1130 EFI_HII_HANDLE
*HiiHandles
;
1131 EFI_HII_HANDLE HiiHandle
;
1133 ASSERT (DevicePath
!= NULL
);
1135 TmpDevicePath
= DevicePath
;
1137 // Locate Device Path Protocol handle buffer
1139 Status
= gBS
->LocateDevicePath (
1140 &gEfiDevicePathProtocolGuid
,
1144 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1149 // Retrieve all HII Handles from HII database
1151 HiiHandles
= HiiGetHiiHandles (NULL
);
1152 if (HiiHandles
== NULL
) {
1157 // Search Hii Handle by Driver Handle
1160 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1161 Status
= mHiiDatabase
->GetPackageListHandle (
1166 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1167 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1168 HiiHandle
= HiiHandles
[Index
];
1172 if (HiiHandle
!= NULL
) {
1178 FreePool (HiiHandles
);
1183 Find HII Handle in the HII database associated with given form set guid.
1185 If FormSetGuid is NULL, then ASSERT.
1187 @param ComparingGuid FormSet Guid associated with the HII package list
1190 @retval Handle HII package list Handle associated with the Device
1192 @retval NULL Hii Package list handle is not found.
1196 FormSetGuidToHiiHandle (
1197 EFI_GUID
*ComparingGuid
1200 EFI_HII_HANDLE
*HiiHandles
;
1201 EFI_HII_HANDLE HiiHandle
;
1204 ASSERT (ComparingGuid
!= NULL
);
1208 // Get all the Hii handles
1210 HiiHandles
= HiiGetHiiHandles (NULL
);
1211 ASSERT (HiiHandles
!= NULL
);
1214 // Search for formset of each class type
1216 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1217 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1218 HiiHandle
= HiiHandles
[Index
];
1222 if (HiiHandle
!= NULL
) {
1227 FreePool (HiiHandles
);
1233 check how to process the changed data in current form or form set.
1235 @param Selection On input, Selection tell setup browser the information
1236 about the Selection, form and formset to be displayed.
1237 On output, Selection return the screen item that is selected
1240 @param Scope Data save or discard scope, form or formset.
1242 @retval TRUE Success process the changed data, will return to the parent form.
1243 @retval FALSE Reject to process the changed data, will stay at current form.
1246 ProcessChangedData (
1247 IN OUT UI_MENU_SELECTION
*Selection
,
1248 IN BROWSER_SETTING_SCOPE Scope
1255 switch (mFormDisplay
->ConfirmDataChange()) {
1256 case BROWSER_ACTION_DISCARD
:
1257 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1260 case BROWSER_ACTION_SUBMIT
:
1261 Status
= SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1262 if (EFI_ERROR (Status
)) {
1267 case BROWSER_ACTION_NONE
:
1273 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1283 Find parent formset menu(the first menu which has different formset) for current menu.
1284 If not find, just return to the first menu.
1286 @param Selection The selection info.
1291 IN OUT UI_MENU_SELECTION
*Selection
1294 FORM_ENTRY_INFO
*CurrentMenu
;
1295 FORM_ENTRY_INFO
*ParentMenu
;
1297 CurrentMenu
= Selection
->CurrentMenu
;
1298 ParentMenu
= UiFindParentMenu(CurrentMenu
, FormSetLevel
);
1300 if (ParentMenu
!= NULL
) {
1301 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1302 Selection
->Handle
= ParentMenu
->HiiHandle
;
1303 Selection
->FormId
= ParentMenu
->FormId
;
1304 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1306 Selection
->FormId
= CurrentMenu
->FormId
;
1307 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1310 Selection
->Statement
= NULL
;
1314 Process the goto op code, update the info in the selection structure.
1316 @param Statement The statement belong to goto op code.
1317 @param Selection The selection info.
1319 @retval EFI_SUCCESS The menu process successfully.
1320 @return Other value if the process failed.
1324 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1325 IN OUT UI_MENU_SELECTION
*Selection
1329 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1330 FORM_BROWSER_FORM
*RefForm
;
1332 EFI_HII_HANDLE HiiHandle
;
1334 Status
= EFI_SUCCESS
;
1339 // Prepare the device path check, get the device path info first.
1341 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1342 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1346 // Check whether the device path string is a valid string.
1348 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1349 if (Selection
->Form
->ModalForm
) {
1354 // Goto another Hii Package list
1356 if (mPathFromText
!= NULL
) {
1357 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1358 if (DevicePath
!= NULL
) {
1359 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1360 FreePool (DevicePath
);
1362 FreePool (StringPtr
);
1365 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1367 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND
, NULL
, NULL
, NULL
);
1368 FreePool (StringPtr
);
1372 if (HiiHandle
!= Selection
->Handle
) {
1374 // Goto another Formset, check for uncommitted data
1376 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1377 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1378 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1384 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1385 Selection
->Handle
= HiiHandle
;
1386 if (Selection
->Handle
== NULL
) {
1388 // If target Hii Handle not found, exit current formset.
1390 FindParentFormSet(Selection
);
1394 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1395 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1396 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1397 } else if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &gZeroGuid
)) {
1398 if (Selection
->Form
->ModalForm
) {
1401 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1403 // Goto another Formset, check for uncommitted data
1405 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1406 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1407 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1413 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1414 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1415 if (Selection
->Handle
== NULL
) {
1417 // If target Hii Handle not found, exit current formset.
1419 FindParentFormSet(Selection
);
1423 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1424 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1425 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1426 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1428 // Goto another Form, check for uncommitted data
1430 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1431 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1432 if (!ProcessChangedData (Selection
, FormLevel
)) {
1438 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1439 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1440 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1442 // Form is suppressed.
1444 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
1449 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1450 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1451 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1452 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1460 Process Question Config.
1462 @param Selection The UI menu selection.
1463 @param Question The Question to be peocessed.
1465 @retval EFI_SUCCESS Question Config process success.
1466 @retval Other Question Config process fail.
1470 ProcessQuestionConfig (
1471 IN UI_MENU_SELECTION
*Selection
,
1472 IN FORM_BROWSER_STATEMENT
*Question
1479 if (Question
->QuestionConfig
== 0) {
1486 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1487 if (ConfigResp
== NULL
) {
1488 return EFI_NOT_FOUND
;
1489 } else if (ConfigResp
[0] == L
'\0') {
1494 // Send config to Configuration Driver
1496 Status
= mHiiConfigRouting
->RouteConfig (
1507 Process the user input data.
1509 @param UserInput The user input data.
1511 @retval EFI_SUCESSS This function always return successfully for now.
1516 IN USER_INPUT
*UserInput
1520 FORM_BROWSER_STATEMENT
*Statement
;
1522 Status
= EFI_SUCCESS
;
1526 // When Exit from FormDisplay function, one of the below two cases must be true.
1528 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1531 // Remove the last highligh question id, this id will update when show next form.
1533 gCurrentSelection
->QuestionId
= 0;
1534 if (UserInput
->SelectedStatement
!= NULL
){
1535 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1536 ASSERT (Statement
!= NULL
);
1539 // This question is the current user select one,record it and later
1540 // show it as the highlight question.
1542 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1544 // For statement like text, actio, it not has question id.
1545 // So use FakeQuestionId to save the question.
1547 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1548 mCurFakeQestId
= Statement
->FakeQuestionId
;
1555 // First process the Action field in USER_INPUT.
1557 if (UserInput
->Action
!= 0) {
1558 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1559 gCurrentSelection
->Statement
= NULL
;
1561 ASSERT (Statement
!= NULL
);
1562 gCurrentSelection
->Statement
= Statement
;
1563 switch (Statement
->Operand
) {
1564 case EFI_IFR_REF_OP
:
1565 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1568 case EFI_IFR_ACTION_OP
:
1570 // Process the Config string <ConfigResp>
1572 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1575 case EFI_IFR_RESET_BUTTON_OP
:
1577 // Reset Question to default value specified by DefaultId
1579 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1580 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1584 switch (Statement
->Operand
) {
1585 case EFI_IFR_STRING_OP
:
1586 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1587 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1588 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1589 FreePool (UserInput
->InputValue
.Buffer
);
1592 case EFI_IFR_PASSWORD_OP
:
1593 if (UserInput
->InputValue
.Buffer
== NULL
) {
1595 // User not input new password, just return.
1600 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1601 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1602 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1603 FreePool (UserInput
->InputValue
.Buffer
);
1605 // Two password match, send it to Configuration Driver
1607 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1608 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1610 // Clean the value after saved it.
1612 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1613 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1615 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1619 case EFI_IFR_ORDERED_LIST_OP
:
1620 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1624 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1636 Display form and wait for user to select one menu option, then return it.
1638 @retval EFI_SUCESSS This function always return successfully for now.
1647 USER_INPUT UserInput
;
1648 FORM_ENTRY_INFO
*CurrentMenu
;
1650 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1653 // Update the menu history data.
1655 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1656 if (CurrentMenu
== NULL
) {
1658 // Current menu not found, add it to the menu tree
1660 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1661 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1662 ASSERT (CurrentMenu
!= NULL
);
1666 // Back up the form view history data for this form.
1668 UiCopyMenuList(&gCurrentSelection
->Form
->FormViewListHead
, &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
1670 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1672 if (gCurrentSelection
->QuestionId
== 0) {
1674 // Highlight not specified, fetch it from cached menu
1676 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1679 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1680 if (EFI_ERROR (Status
)) {
1684 UpdateDisplayFormData ();
1686 ASSERT (gDisplayFormData
.BrowserStatus
== BROWSER_SUCCESS
);
1687 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1688 if (EFI_ERROR (Status
)) {
1689 FreeDisplayFormData();
1693 Status
= ProcessUserInput (&UserInput
);
1694 FreeDisplayFormData();
1699 Functions which are registered to receive notification of
1700 database events have this prototype. The actual event is encoded
1701 in NotifyType. The following table describes how PackageType,
1702 PackageGuid, Handle, and Package are used for each of the
1705 @param PackageType Package type of the notification.
1707 @param PackageGuid If PackageType is
1708 EFI_HII_PACKAGE_TYPE_GUID, then this is
1709 the pointer to the GUID from the Guid
1710 field of EFI_HII_PACKAGE_GUID_HEADER.
1711 Otherwise, it must be NULL.
1713 @param Package Points to the package referred to by the
1714 notification Handle The handle of the package
1715 list which contains the specified package.
1717 @param Handle The HII handle.
1719 @param NotifyType The type of change concerning the
1721 EFI_HII_DATABASE_NOTIFY_TYPE.
1727 IN UINT8 PackageType
,
1728 IN CONST EFI_GUID
*PackageGuid
,
1729 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1730 IN EFI_HII_HANDLE Handle
,
1731 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1734 mHiiPackageListUpdated
= TRUE
;
1740 Update the NV flag info for this form set.
1742 @param FormSet FormSet data structure.
1746 IsNvUpdateRequiredForFormSet (
1747 IN FORM_BROWSER_FORMSET
*FormSet
1751 FORM_BROWSER_FORM
*Form
;
1755 // Not finished question initialization, return FALSE.
1757 if (!FormSet
->QuestionInited
) {
1763 Link
= GetFirstNode (&FormSet
->FormListHead
);
1764 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1765 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1767 RetVal
= IsNvUpdateRequiredForForm(Form
);
1772 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1779 Update the NvUpdateRequired flag for a form.
1781 @param Form Form data structure.
1785 IsNvUpdateRequiredForForm (
1786 IN FORM_BROWSER_FORM
*Form
1790 FORM_BROWSER_STATEMENT
*Statement
;
1792 Link
= GetFirstNode (&Form
->StatementListHead
);
1793 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1794 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1796 if (Statement
->ValueChanged
) {
1800 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1807 Find menu which will show next time.
1809 @param Selection On input, Selection tell setup browser the information
1810 about the Selection, form and formset to be displayed.
1811 On output, Selection return the screen item that is selected
1813 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1814 else, we need to exit current formset.
1816 @retval TRUE Exit current form.
1817 @retval FALSE User press ESC and keep in current form.
1821 IN OUT UI_MENU_SELECTION
*Selection
,
1822 IN BROWSER_SETTING_SCOPE SettingLevel
1825 FORM_ENTRY_INFO
*CurrentMenu
;
1826 FORM_ENTRY_INFO
*ParentMenu
;
1827 BROWSER_SETTING_SCOPE Scope
;
1829 CurrentMenu
= Selection
->CurrentMenu
;
1830 Scope
= FormSetLevel
;
1832 ParentMenu
= UiFindParentMenu(CurrentMenu
, SettingLevel
);
1833 while (ParentMenu
!= NULL
&& !ValidateHiiHandle(ParentMenu
->HiiHandle
)) {
1834 ParentMenu
= UiFindParentMenu(ParentMenu
, SettingLevel
);
1837 if (ParentMenu
!= NULL
) {
1838 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1841 Scope
= FormSetLevel
;
1846 // Form Level Check whether the data is changed.
1848 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1849 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1850 if (!ProcessChangedData(Selection
, gBrowserSettingScope
)) {
1855 if (ParentMenu
!= NULL
) {
1857 // ParentMenu is found. Then, go to it.
1859 if (Scope
== FormLevel
) {
1860 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
1862 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1863 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1864 Selection
->Handle
= ParentMenu
->HiiHandle
;
1867 Selection
->Statement
= NULL
;
1869 Selection
->FormId
= ParentMenu
->FormId
;
1870 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1873 // Clear highlight record for this menu
1875 CurrentMenu
->QuestionId
= 0;
1880 // Current in root page, exit the SendForm
1882 Selection
->Action
= UI_ACTION_EXIT
;
1888 Call the call back function for the question and process the return action.
1890 @param Selection On input, Selection tell setup browser the information
1891 about the Selection, form and formset to be displayed.
1892 On output, Selection return the screen item that is selected
1894 @param FormSet The formset this question belong to.
1895 @param Form The form this question belong to.
1896 @param Question The Question which need to call.
1897 @param Action The action request.
1898 @param SkipSaveOrDiscard Whether skip save or discard action.
1900 @retval EFI_SUCCESS The call back function excutes successfully.
1901 @return Other value if the call back function failed to excute.
1904 ProcessCallBackFunction (
1905 IN OUT UI_MENU_SELECTION
*Selection
,
1906 IN FORM_BROWSER_FORMSET
*FormSet
,
1907 IN FORM_BROWSER_FORM
*Form
,
1908 IN FORM_BROWSER_STATEMENT
*Question
,
1909 IN EFI_BROWSER_ACTION Action
,
1910 IN BOOLEAN SkipSaveOrDiscard
1914 EFI_STATUS InternalStatus
;
1915 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1916 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1917 EFI_HII_VALUE
*HiiValue
;
1918 EFI_IFR_TYPE_VALUE
*TypeValue
;
1919 FORM_BROWSER_STATEMENT
*Statement
;
1920 BOOLEAN SubmitFormIsRequired
;
1921 BOOLEAN DiscardFormIsRequired
;
1924 BROWSER_SETTING_SCOPE SettingLevel
;
1925 EFI_IFR_TYPE_VALUE BackUpValue
;
1926 UINT8
*BackUpBuffer
;
1929 ConfigAccess
= FormSet
->ConfigAccess
;
1930 SubmitFormIsRequired
= FALSE
;
1931 SettingLevel
= FormSetLevel
;
1932 DiscardFormIsRequired
= FALSE
;
1934 Status
= EFI_SUCCESS
;
1935 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1936 BackUpBuffer
= NULL
;
1938 if (ConfigAccess
== NULL
) {
1942 Link
= GetFirstNode (&Form
->StatementListHead
);
1943 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1944 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1945 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1948 // if Question != NULL, only process the question. Else, process all question in this form.
1950 if ((Question
!= NULL
) && (Statement
!= Question
)) {
1954 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
1959 // Check whether Statement is disabled.
1961 if (Statement
->Expression
!= NULL
) {
1962 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
1967 HiiValue
= &Statement
->HiiValue
;
1968 TypeValue
= &HiiValue
->Value
;
1969 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
1971 // For OrderedList, passing in the value buffer to Callback()
1973 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
1977 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
1979 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
1980 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
1981 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
+ sizeof(CHAR16
), Statement
->BufferValue
);
1982 ASSERT (BackUpBuffer
!= NULL
);
1984 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1988 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1989 Status
= ConfigAccess
->Callback (
1992 Statement
->QuestionId
,
1997 if (!EFI_ERROR (Status
)) {
1999 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2001 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2002 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2003 ASSERT (NewString
!= NULL
);
2005 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2006 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2007 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2009 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2011 FreePool (NewString
);
2015 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2018 case EFI_BROWSER_ACTION_CHANGED
:
2019 switch (ActionRequest
) {
2020 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2021 DiscardFormIsRequired
= TRUE
;
2022 gResetRequired
= TRUE
;
2026 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2027 SubmitFormIsRequired
= TRUE
;
2031 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2032 DiscardFormIsRequired
= TRUE
;
2036 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2037 SubmitFormIsRequired
= TRUE
;
2038 SettingLevel
= FormLevel
;
2042 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2043 DiscardFormIsRequired
= TRUE
;
2044 SettingLevel
= FormLevel
;
2048 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2049 SubmitFormIsRequired
= TRUE
;
2050 SettingLevel
= FormLevel
;
2053 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2054 DiscardFormIsRequired
= TRUE
;
2055 SettingLevel
= FormLevel
;
2063 case EFI_BROWSER_ACTION_CHANGING
:
2065 // Do the question validation.
2067 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2068 if (!EFI_ERROR (Status
)) {
2070 // According the spec, return value from call back of "changing" and
2071 // "retrieve" should update to the question's temp buffer.
2073 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2077 case EFI_BROWSER_ACTION_RETRIEVE
:
2079 // According the spec, return value from call back of "changing" and
2080 // "retrieve" should update to the question's temp buffer.
2082 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2090 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2091 // then the browser will use the value passed to Callback() and ignore the
2092 // value returned by Callback().
2094 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2095 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2096 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
+ sizeof(CHAR16
));
2098 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2102 // Do the question validation.
2104 InternalStatus
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2105 if (!EFI_ERROR (InternalStatus
)) {
2106 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2111 // According the spec, return fail from call back of "changing" and
2112 // "retrieve", should restore the question's value.
2114 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) {
2115 if (Statement
->Storage
!= NULL
) {
2116 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2117 } else if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
2118 ProcessCallBackFunction (Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2122 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2123 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2126 if (Status
== EFI_UNSUPPORTED
) {
2128 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2130 Status
= EFI_SUCCESS
;
2134 if (BackUpBuffer
!= NULL
) {
2135 FreePool (BackUpBuffer
);
2139 // If Question != NULL, means just process one question
2140 // and if code reach here means this question has finished
2141 // processing, so just break.
2143 if (Question
!= NULL
) {
2148 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2149 SubmitForm (FormSet
, Form
, SettingLevel
);
2152 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2153 DiscardForm (FormSet
, Form
, SettingLevel
);
2157 FindNextMenu (Selection
, SettingLevel
);
2164 Call the retrieve type call back function for one question to get the initialize data.
2166 This function only used when in the initialize stage, because in this stage, the
2167 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2169 @param ConfigAccess The config access protocol produced by the hii driver.
2170 @param Statement The Question which need to call.
2171 @param FormSet The formset this question belong to.
2173 @retval EFI_SUCCESS The call back function excutes successfully.
2174 @return Other value if the call back function failed to excute.
2177 ProcessRetrieveForQuestion (
2178 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2179 IN FORM_BROWSER_STATEMENT
*Statement
,
2180 IN FORM_BROWSER_FORMSET
*FormSet
2184 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2185 EFI_HII_VALUE
*HiiValue
;
2186 EFI_IFR_TYPE_VALUE
*TypeValue
;
2189 Status
= EFI_SUCCESS
;
2190 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2192 if (((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) || ConfigAccess
== NULL
) {
2193 return EFI_UNSUPPORTED
;
2196 HiiValue
= &Statement
->HiiValue
;
2197 TypeValue
= &HiiValue
->Value
;
2198 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2200 // For OrderedList, passing in the value buffer to Callback()
2202 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2205 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2206 Status
= ConfigAccess
->Callback (
2208 EFI_BROWSER_ACTION_RETRIEVE
,
2209 Statement
->QuestionId
,
2214 if (!EFI_ERROR (Status
) && HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2215 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2216 ASSERT (NewString
!= NULL
);
2218 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2219 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2220 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2222 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2224 FreePool (NewString
);
2231 The worker function that send the displays to the screen. On output,
2232 the selection made by user is returned.
2234 @param Selection On input, Selection tell setup browser the information
2235 about the Selection, form and formset to be displayed.
2236 On output, Selection return the screen item that is selected
2239 @retval EFI_SUCCESS The page is displayed successfully.
2240 @return Other value if the page failed to be diplayed.
2245 IN OUT UI_MENU_SELECTION
*Selection
2250 EFI_HANDLE NotifyHandle
;
2251 FORM_BROWSER_STATEMENT
*Statement
;
2252 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2254 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2257 // Register notify for Form package update
2259 Status
= mHiiDatabase
->RegisterPackageNotify (
2261 EFI_HII_PACKAGE_FORMS
,
2264 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2267 if (EFI_ERROR (Status
)) {
2272 // Initialize current settings of Questions in this FormSet
2274 InitializeCurrentSetting (Selection
->FormSet
);
2277 // Initilize Action field.
2279 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2282 // Clean the mCurFakeQestId value is formset refreshed.
2288 // IFR is updated, force to reparse the IFR binary
2289 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and
2290 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.
2292 if (mHiiPackageListUpdated
) {
2293 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2294 mHiiPackageListUpdated
= FALSE
;
2299 // Initialize Selection->Form
2301 if (Selection
->FormId
== 0) {
2303 // Zero FormId indicates display the first Form in a FormSet
2305 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2307 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2308 Selection
->FormId
= Selection
->Form
->FormId
;
2310 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2313 if (Selection
->Form
== NULL
) {
2315 // No Form to display
2317 Status
= EFI_NOT_FOUND
;
2322 // Check Form is suppressed.
2324 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2325 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2327 // Form is suppressed.
2329 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
2330 Status
= EFI_NOT_FOUND
;
2336 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2337 // for each question with callback flag.
2338 // New form may be the first form, or the different form after another form close.
2340 if (((Selection
->Handle
!= mCurrentHiiHandle
) ||
2341 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2342 (Selection
->FormId
!= mCurrentFormId
))) {
2344 // Update Retrieve flag.
2346 mFinishRetrieveCall
= FALSE
;
2349 // Keep current form information
2351 mCurrentHiiHandle
= Selection
->Handle
;
2352 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2353 mCurrentFormId
= Selection
->FormId
;
2355 if (ConfigAccess
!= NULL
) {
2356 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2357 if (EFI_ERROR (Status
)) {
2362 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2364 if (mHiiPackageListUpdated
) {
2365 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2366 mHiiPackageListUpdated
= FALSE
;
2373 // Load Questions' Value for display
2375 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2376 if (EFI_ERROR (Status
)) {
2380 if (!mFinishRetrieveCall
) {
2382 // Finish call RETRIEVE callback for this form.
2384 mFinishRetrieveCall
= TRUE
;
2386 if (ConfigAccess
!= NULL
) {
2387 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2388 if (EFI_ERROR (Status
)) {
2393 // IFR is updated during callback of open form, force to reparse the IFR binary
2395 if (mHiiPackageListUpdated
) {
2396 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2397 mHiiPackageListUpdated
= FALSE
;
2406 Status
= DisplayForm ();
2407 if (EFI_ERROR (Status
)) {
2412 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2414 Statement
= Selection
->Statement
;
2415 if (Statement
!= NULL
) {
2416 if ((ConfigAccess
!= NULL
) &&
2417 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2418 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2419 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2420 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2422 // Process dynamic update ref opcode.
2424 if (!EFI_ERROR (Status
)) {
2425 Status
= ProcessGotoOpCode(Statement
, Selection
);
2429 // Callback return error status or status return from process goto opcode.
2431 if (EFI_ERROR (Status
)) {
2433 // Cross reference will not be taken
2435 Selection
->FormId
= Selection
->Form
->FormId
;
2436 Selection
->QuestionId
= 0;
2441 // Verify whether question value has checked, update the ValueChanged flag in Question.
2443 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2445 if (!EFI_ERROR (Status
) &&
2446 (Statement
->Operand
!= EFI_IFR_REF_OP
) &&
2447 ((Statement
->Storage
== NULL
) || (Statement
->Storage
!= NULL
&& Statement
->ValueChanged
))) {
2449 // Only question value has been changed, browser will trig CHANGED callback.
2451 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2455 // Do the question validation.
2457 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2458 if (!EFI_ERROR (Status
) && (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2459 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2461 // Verify whether question value has checked, update the ValueChanged flag in Question.
2463 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2468 // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here,
2469 // trig the gResetFlag.
2471 if ((Status
== EFI_SUCCESS
) &&
2472 (Statement
->Storage
== NULL
) &&
2473 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2474 gResetRequired
= TRUE
;
2479 // Check whether Exit flag is TRUE.
2481 if (gExitRequired
) {
2482 switch (gBrowserSettingScope
) {
2484 Selection
->Action
= UI_ACTION_EXIT
;
2489 FindNextMenu (Selection
, gBrowserSettingScope
);
2496 gExitRequired
= FALSE
;
2500 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2501 // for each question with callback flag.
2503 if ((ConfigAccess
!= NULL
) &&
2504 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2505 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2506 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2507 (Selection
->FormId
!= mCurrentFormId
))) {
2509 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2510 if (EFI_ERROR (Status
)) {
2514 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2518 // Reset current form information to the initial setting when error happens or form exit.
2520 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2521 mCurrentHiiHandle
= NULL
;
2522 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2527 // Unregister notify for Form package update
2529 mHiiDatabase
->UnregisterPackageNotify (