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 // treat formset as statement outside the form,get its opcode.
551 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
552 ASSERT (DisplayStatement
!= NULL
);
554 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
555 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
556 DisplayStatement
->OpCode
= gCurrentSelection
->FormSet
->OpCode
;
558 InitializeListHead (&DisplayStatement
->NestStatementList
);
559 InitializeListHead (&DisplayStatement
->OptionListHead
);
561 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
564 // Process the statement in this form.
566 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
567 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
568 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
569 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
572 // This statement can't be show, skip it.
574 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
579 // Check the extra attribute.
581 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
582 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
586 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
587 ASSERT (DisplayStatement
!= NULL
);
590 // Initialize this statement and add it to the display form.
592 InitializeDisplayStatement(DisplayStatement
, Statement
);
595 // Set the extra attribute.
597 DisplayStatement
->Attribute
|= ExtraAttribute
;
599 if (Statement
->Storage
!= NULL
) {
604 // Get the minimal refresh interval value for later use.
606 if ((Statement
->RefreshInterval
!= 0) &&
607 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
608 MinRefreshInterval
= Statement
->RefreshInterval
;
613 // Create the periodic timer for refresh interval statement.
615 if (MinRefreshInterval
!= 0) {
616 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
617 ASSERT_EFI_ERROR (Status
);
618 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
619 ASSERT_EFI_ERROR (Status
);
621 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
622 ASSERT (EventNode
!= NULL
);
623 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
624 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
628 // Create the refresh event process function for Form.
630 if (!CompareGuid (&gCurrentSelection
->Form
->RefreshGuid
, &gZeroGuid
)) {
631 CreateRefreshEventForForm (gCurrentSelection
->Form
);
632 if (gDisplayFormData
.FormRefreshEvent
== NULL
) {
633 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
638 // Update hotkey list field.
640 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
647 Initialize the SettingChangedFlag variable in the display form.
651 UpdateDataChangedFlag (
656 FORM_BROWSER_FORMSET
*LocalFormSet
;
658 gDisplayFormData
.SettingChangedFlag
= FALSE
;
660 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
661 gDisplayFormData
.SettingChangedFlag
= TRUE
;
666 // Base on the system level to check whether need to show the NV flag.
668 switch (gBrowserSettingScope
) {
671 // Check the maintain list to see whether there is any change.
673 Link
= GetFirstNode (&gBrowserFormSetList
);
674 while (!IsNull (&gBrowserFormSetList
, Link
)) {
675 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
676 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
677 gDisplayFormData
.SettingChangedFlag
= TRUE
;
680 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
685 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
686 gDisplayFormData
.SettingChangedFlag
= TRUE
;
698 Initialize the Display form structure data.
702 InitializeDisplayFormData (
708 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
709 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
710 gDisplayFormData
.ImageId
= 0;
711 gDisplayFormData
.AnimationId
= 0;
713 InitializeListHead (&gDisplayFormData
.StatementListHead
);
714 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
715 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
717 Status
= gBS
->CreateEvent (
720 SetupBrowserEmptyFunction
,
724 ASSERT_EFI_ERROR (Status
);
729 Free the kotkey info saved in form data.
737 BROWSER_HOT_KEY
*HotKey
;
740 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
741 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
742 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
744 RemoveEntryList (&HotKey
->Link
);
746 FreePool (HotKey
->KeyData
);
747 FreePool (HotKey
->HelpString
);
754 Update the Display form structure data.
758 UpdateDisplayFormData (
762 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
763 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
764 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
765 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
767 gDisplayFormData
.Attribute
= 0;
768 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
769 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
771 gDisplayFormData
.FormRefreshEvent
= NULL
;
772 gDisplayFormData
.HighLightedStatement
= NULL
;
774 UpdateDataChangedFlag ();
776 AddStatementToDisplayForm ();
781 Free the Display Statement structure data.
783 @param StatementList Point to the statement list which need to be free.
788 LIST_ENTRY
*StatementList
792 LIST_ENTRY
*OptionLink
;
793 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
794 DISPLAY_QUESTION_OPTION
*Option
;
797 // Free Statements/Questions
799 while (!IsListEmpty (StatementList
)) {
800 Link
= GetFirstNode (StatementList
);
801 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
806 while (!IsListEmpty (&Statement
->OptionListHead
)) {
807 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
808 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
809 RemoveEntryList (&Option
->Link
);
814 // Free nest statement List
816 if (!IsListEmpty (&Statement
->NestStatementList
)) {
817 FreeStatementData(&Statement
->NestStatementList
);
820 RemoveEntryList (&Statement
->DisplayLink
);
821 FreePool (Statement
);
827 Free the Display form structure data.
831 FreeDisplayFormData (
835 FreeStatementData (&gDisplayFormData
.StatementListHead
);
836 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
845 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
847 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
849 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
852 FORM_BROWSER_STATEMENT
*
853 GetBrowserStatement (
854 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
857 FORM_BROWSER_STATEMENT
*Statement
;
860 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
861 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
862 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
864 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
868 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
875 Update the ValueChanged status for questions in this form.
877 @param FormSet FormSet data structure.
878 @param Form Form data structure.
882 UpdateStatementStatusForForm (
883 IN FORM_BROWSER_FORMSET
*FormSet
,
884 IN FORM_BROWSER_FORM
*Form
888 FORM_BROWSER_STATEMENT
*Question
;
890 Link
= GetFirstNode (&Form
->StatementListHead
);
891 while (!IsNull (&Form
->StatementListHead
, Link
)) {
892 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
893 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
896 // For password opcode, not set the the value changed flag.
898 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
902 IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
907 Update the ValueChanged status for questions in this formset.
909 @param FormSet FormSet data structure.
913 UpdateStatementStatusForFormSet (
914 IN FORM_BROWSER_FORMSET
*FormSet
918 FORM_BROWSER_FORM
*Form
;
920 Link
= GetFirstNode (&FormSet
->FormListHead
);
921 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
922 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
923 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
925 UpdateStatementStatusForForm (FormSet
, Form
);
930 Update the ValueChanged status for questions.
932 @param FormSet FormSet data structure.
933 @param Form Form data structure.
934 @param SettingScope Setting Scope for Default action.
938 UpdateStatementStatus (
939 IN FORM_BROWSER_FORMSET
*FormSet
,
940 IN FORM_BROWSER_FORM
*Form
,
941 IN BROWSER_SETTING_SCOPE SettingScope
945 FORM_BROWSER_FORMSET
*LocalFormSet
;
947 switch (SettingScope
) {
949 Link
= GetFirstNode (&gBrowserFormSetList
);
950 while (!IsNull (&gBrowserFormSetList
, Link
)) {
951 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
952 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
953 if (!ValidateFormSet(LocalFormSet
)) {
957 UpdateStatementStatusForFormSet (LocalFormSet
);
962 UpdateStatementStatusForFormSet (FormSet
);
966 UpdateStatementStatusForForm (FormSet
, Form
);
976 Process the action request in user input.
978 @param Action The user input action request info.
979 @param DefaultId The user input default Id info.
981 @retval EFI_SUCESSS This function always return successfully for now.
991 // This is caused by use press ESC, and it should not combine with other action type.
993 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
994 FindNextMenu (gCurrentSelection
, FormLevel
);
999 // Below is normal hotkey trigged action, these action maybe combine with each other.
1001 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
1002 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1005 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
1006 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1007 UpdateStatementStatus (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1010 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
1011 SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1014 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1015 gResetRequired
= TRUE
;
1018 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1020 // Form Exit without saving, Similar to ESC Key.
1021 // FormSet Exit without saving, Exit SendForm.
1022 // System Exit without saving, CallExitHandler and Exit SendForm.
1024 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1025 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1026 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1027 } else if (gBrowserSettingScope
== SystemLevel
) {
1028 if (ExitHandlerFunction
!= NULL
) {
1029 ExitHandlerFunction ();
1031 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1039 Check whether the formset guid is in this Hii package list.
1041 @param HiiHandle The HiiHandle for this HII package list.
1042 @param FormSetGuid The formset guid for the request formset.
1044 @retval TRUE Find the formset guid.
1045 @retval FALSE Not found the formset guid.
1049 GetFormsetGuidFromHiiHandle (
1050 IN EFI_HII_HANDLE HiiHandle
,
1051 IN EFI_GUID
*FormSetGuid
1054 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1058 UINT32 PackageListLength
;
1059 EFI_HII_PACKAGE_HEADER PackageHeader
;
1066 HiiPackageList
= NULL
;
1069 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1070 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1071 HiiPackageList
= AllocatePool (BufferSize
);
1072 ASSERT (HiiPackageList
!= NULL
);
1074 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1076 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1081 // Get Form package from this HII package List
1083 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1085 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1087 while (Offset
< PackageListLength
) {
1088 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1089 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1090 Offset
+= PackageHeader
.Length
;
1092 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1094 // Search FormSet in this Form Package
1096 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1097 while (Offset2
< PackageHeader
.Length
) {
1098 OpCodeData
= Package
+ Offset2
;
1100 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1101 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1107 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1115 FreePool (HiiPackageList
);
1121 Find HII Handle in the HII database associated with given Device Path.
1123 If DevicePath is NULL, then ASSERT.
1125 @param DevicePath Device Path associated with the HII package list
1127 @param FormsetGuid The formset guid for this formset.
1129 @retval Handle HII package list Handle associated with the Device
1131 @retval NULL Hii Package list handle is not found.
1135 DevicePathToHiiHandle (
1136 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1137 IN EFI_GUID
*FormsetGuid
1141 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1144 EFI_HANDLE DriverHandle
;
1145 EFI_HII_HANDLE
*HiiHandles
;
1146 EFI_HII_HANDLE HiiHandle
;
1148 ASSERT (DevicePath
!= NULL
);
1150 TmpDevicePath
= DevicePath
;
1152 // Locate Device Path Protocol handle buffer
1154 Status
= gBS
->LocateDevicePath (
1155 &gEfiDevicePathProtocolGuid
,
1159 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1164 // Retrieve all HII Handles from HII database
1166 HiiHandles
= HiiGetHiiHandles (NULL
);
1167 if (HiiHandles
== NULL
) {
1172 // Search Hii Handle by Driver Handle
1175 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1176 Status
= mHiiDatabase
->GetPackageListHandle (
1181 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1182 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1183 HiiHandle
= HiiHandles
[Index
];
1187 if (HiiHandle
!= NULL
) {
1193 FreePool (HiiHandles
);
1198 Find HII Handle in the HII database associated with given form set guid.
1200 If FormSetGuid is NULL, then ASSERT.
1202 @param ComparingGuid FormSet Guid associated with the HII package list
1205 @retval Handle HII package list Handle associated with the Device
1207 @retval NULL Hii Package list handle is not found.
1211 FormSetGuidToHiiHandle (
1212 EFI_GUID
*ComparingGuid
1215 EFI_HII_HANDLE
*HiiHandles
;
1216 EFI_HII_HANDLE HiiHandle
;
1219 ASSERT (ComparingGuid
!= NULL
);
1223 // Get all the Hii handles
1225 HiiHandles
= HiiGetHiiHandles (NULL
);
1226 ASSERT (HiiHandles
!= NULL
);
1229 // Search for formset of each class type
1231 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1232 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1233 HiiHandle
= HiiHandles
[Index
];
1237 if (HiiHandle
!= NULL
) {
1242 FreePool (HiiHandles
);
1248 check how to process the changed data in current form or form set.
1250 @param Selection On input, Selection tell setup browser the information
1251 about the Selection, form and formset to be displayed.
1252 On output, Selection return the screen item that is selected
1255 @param Scope Data save or discard scope, form or formset.
1257 @retval TRUE Success process the changed data, will return to the parent form.
1258 @retval FALSE Reject to process the changed data, will stay at current form.
1261 ProcessChangedData (
1262 IN OUT UI_MENU_SELECTION
*Selection
,
1263 IN BROWSER_SETTING_SCOPE Scope
1270 switch (mFormDisplay
->ConfirmDataChange()) {
1271 case BROWSER_ACTION_DISCARD
:
1272 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1275 case BROWSER_ACTION_SUBMIT
:
1276 Status
= SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1277 if (EFI_ERROR (Status
)) {
1282 case BROWSER_ACTION_NONE
:
1288 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1298 Find parent formset menu(the first menu which has different formset) for current menu.
1299 If not find, just return to the first menu.
1301 @param Selection The selection info.
1306 IN OUT UI_MENU_SELECTION
*Selection
1309 FORM_ENTRY_INFO
*CurrentMenu
;
1310 FORM_ENTRY_INFO
*ParentMenu
;
1312 CurrentMenu
= Selection
->CurrentMenu
;
1313 ParentMenu
= UiFindParentMenu(CurrentMenu
, FormSetLevel
);
1315 if (ParentMenu
!= NULL
) {
1316 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1317 Selection
->Handle
= ParentMenu
->HiiHandle
;
1318 Selection
->FormId
= ParentMenu
->FormId
;
1319 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1321 Selection
->FormId
= CurrentMenu
->FormId
;
1322 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1325 Selection
->Statement
= NULL
;
1329 Process the goto op code, update the info in the selection structure.
1331 @param Statement The statement belong to goto op code.
1332 @param Selection The selection info.
1334 @retval EFI_SUCCESS The menu process successfully.
1335 @return Other value if the process failed.
1339 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1340 IN OUT UI_MENU_SELECTION
*Selection
1344 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1345 FORM_BROWSER_FORM
*RefForm
;
1347 EFI_HII_HANDLE HiiHandle
;
1349 Status
= EFI_SUCCESS
;
1354 // Prepare the device path check, get the device path info first.
1356 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1357 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1361 // Check whether the device path string is a valid string.
1363 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1364 if (Selection
->Form
->ModalForm
) {
1369 // Goto another Hii Package list
1371 if (mPathFromText
!= NULL
) {
1372 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1373 if (DevicePath
!= NULL
) {
1374 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1375 FreePool (DevicePath
);
1377 FreePool (StringPtr
);
1380 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1382 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND
, NULL
, NULL
, NULL
);
1383 FreePool (StringPtr
);
1387 if (HiiHandle
!= Selection
->Handle
) {
1389 // Goto another Formset, check for uncommitted data
1391 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1392 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1393 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1399 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1400 Selection
->Handle
= HiiHandle
;
1401 if (Selection
->Handle
== NULL
) {
1403 // If target Hii Handle not found, exit current formset.
1405 FindParentFormSet(Selection
);
1409 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1410 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1411 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1412 } else if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &gZeroGuid
)) {
1413 if (Selection
->Form
->ModalForm
) {
1416 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1418 // Goto another Formset, check for uncommitted data
1420 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1421 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1422 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1428 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1429 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1430 if (Selection
->Handle
== NULL
) {
1432 // If target Hii Handle not found, exit current formset.
1434 FindParentFormSet(Selection
);
1438 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1439 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1440 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1441 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1443 // Goto another Form, check for uncommitted data
1445 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1446 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1447 if (!ProcessChangedData (Selection
, FormLevel
)) {
1453 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1454 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1455 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1457 // Form is suppressed.
1459 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
1464 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1465 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1466 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1467 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1475 Process Question Config.
1477 @param Selection The UI menu selection.
1478 @param Question The Question to be peocessed.
1480 @retval EFI_SUCCESS Question Config process success.
1481 @retval Other Question Config process fail.
1485 ProcessQuestionConfig (
1486 IN UI_MENU_SELECTION
*Selection
,
1487 IN FORM_BROWSER_STATEMENT
*Question
1494 if (Question
->QuestionConfig
== 0) {
1501 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1502 if (ConfigResp
== NULL
) {
1503 return EFI_NOT_FOUND
;
1504 } else if (ConfigResp
[0] == L
'\0') {
1509 // Send config to Configuration Driver
1511 Status
= mHiiConfigRouting
->RouteConfig (
1522 Process the user input data.
1524 @param UserInput The user input data.
1526 @retval EFI_SUCESSS This function always return successfully for now.
1531 IN USER_INPUT
*UserInput
1535 FORM_BROWSER_STATEMENT
*Statement
;
1537 Status
= EFI_SUCCESS
;
1541 // When Exit from FormDisplay function, one of the below two cases must be true.
1543 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1546 // Remove the last highligh question id, this id will update when show next form.
1548 gCurrentSelection
->QuestionId
= 0;
1549 if (UserInput
->SelectedStatement
!= NULL
){
1550 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1551 ASSERT (Statement
!= NULL
);
1554 // This question is the current user select one,record it and later
1555 // show it as the highlight question.
1557 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1559 // For statement like text, actio, it not has question id.
1560 // So use FakeQuestionId to save the question.
1562 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1563 mCurFakeQestId
= Statement
->FakeQuestionId
;
1570 // First process the Action field in USER_INPUT.
1572 if (UserInput
->Action
!= 0) {
1573 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1574 gCurrentSelection
->Statement
= NULL
;
1576 ASSERT (Statement
!= NULL
);
1577 gCurrentSelection
->Statement
= Statement
;
1578 switch (Statement
->Operand
) {
1579 case EFI_IFR_REF_OP
:
1580 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1583 case EFI_IFR_ACTION_OP
:
1585 // Process the Config string <ConfigResp>
1587 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1590 case EFI_IFR_RESET_BUTTON_OP
:
1592 // Reset Question to default value specified by DefaultId
1594 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1595 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1599 switch (Statement
->Operand
) {
1600 case EFI_IFR_STRING_OP
:
1601 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1602 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1603 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1604 FreePool (UserInput
->InputValue
.Buffer
);
1607 case EFI_IFR_PASSWORD_OP
:
1608 if (UserInput
->InputValue
.Buffer
== NULL
) {
1610 // User not input new password, just return.
1615 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1616 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1617 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1618 FreePool (UserInput
->InputValue
.Buffer
);
1620 // Two password match, send it to Configuration Driver
1622 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1623 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1625 // Clean the value after saved it.
1627 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1628 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1630 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1634 case EFI_IFR_ORDERED_LIST_OP
:
1635 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1639 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1651 Display form and wait for user to select one menu option, then return it.
1653 @retval EFI_SUCESSS This function always return successfully for now.
1662 USER_INPUT UserInput
;
1663 FORM_ENTRY_INFO
*CurrentMenu
;
1665 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1668 // Update the menu history data.
1670 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1671 if (CurrentMenu
== NULL
) {
1673 // Current menu not found, add it to the menu tree
1675 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1676 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1677 ASSERT (CurrentMenu
!= NULL
);
1681 // Back up the form view history data for this form.
1683 UiCopyMenuList(&gCurrentSelection
->Form
->FormViewListHead
, &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
1685 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1687 if (gCurrentSelection
->QuestionId
== 0) {
1689 // Highlight not specified, fetch it from cached menu
1691 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1694 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1695 if (EFI_ERROR (Status
)) {
1699 UpdateDisplayFormData ();
1701 ASSERT (gDisplayFormData
.BrowserStatus
== BROWSER_SUCCESS
);
1702 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1703 if (EFI_ERROR (Status
)) {
1704 FreeDisplayFormData();
1708 Status
= ProcessUserInput (&UserInput
);
1709 FreeDisplayFormData();
1714 Functions which are registered to receive notification of
1715 database events have this prototype. The actual event is encoded
1716 in NotifyType. The following table describes how PackageType,
1717 PackageGuid, Handle, and Package are used for each of the
1720 @param PackageType Package type of the notification.
1722 @param PackageGuid If PackageType is
1723 EFI_HII_PACKAGE_TYPE_GUID, then this is
1724 the pointer to the GUID from the Guid
1725 field of EFI_HII_PACKAGE_GUID_HEADER.
1726 Otherwise, it must be NULL.
1728 @param Package Points to the package referred to by the
1729 notification Handle The handle of the package
1730 list which contains the specified package.
1732 @param Handle The HII handle.
1734 @param NotifyType The type of change concerning the
1736 EFI_HII_DATABASE_NOTIFY_TYPE.
1742 IN UINT8 PackageType
,
1743 IN CONST EFI_GUID
*PackageGuid
,
1744 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1745 IN EFI_HII_HANDLE Handle
,
1746 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1749 mHiiPackageListUpdated
= TRUE
;
1755 Update the NV flag info for this form set.
1757 @param FormSet FormSet data structure.
1761 IsNvUpdateRequiredForFormSet (
1762 IN FORM_BROWSER_FORMSET
*FormSet
1766 FORM_BROWSER_FORM
*Form
;
1770 // Not finished question initialization, return FALSE.
1772 if (!FormSet
->QuestionInited
) {
1778 Link
= GetFirstNode (&FormSet
->FormListHead
);
1779 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1780 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1782 RetVal
= IsNvUpdateRequiredForForm(Form
);
1787 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1794 Update the NvUpdateRequired flag for a form.
1796 @param Form Form data structure.
1800 IsNvUpdateRequiredForForm (
1801 IN FORM_BROWSER_FORM
*Form
1805 FORM_BROWSER_STATEMENT
*Statement
;
1807 Link
= GetFirstNode (&Form
->StatementListHead
);
1808 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1809 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1811 if (Statement
->ValueChanged
) {
1815 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1822 Find menu which will show next time.
1824 @param Selection On input, Selection tell setup browser the information
1825 about the Selection, form and formset to be displayed.
1826 On output, Selection return the screen item that is selected
1828 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1829 else, we need to exit current formset.
1831 @retval TRUE Exit current form.
1832 @retval FALSE User press ESC and keep in current form.
1836 IN OUT UI_MENU_SELECTION
*Selection
,
1837 IN BROWSER_SETTING_SCOPE SettingLevel
1840 FORM_ENTRY_INFO
*CurrentMenu
;
1841 FORM_ENTRY_INFO
*ParentMenu
;
1842 BROWSER_SETTING_SCOPE Scope
;
1844 CurrentMenu
= Selection
->CurrentMenu
;
1845 Scope
= FormSetLevel
;
1847 ParentMenu
= UiFindParentMenu(CurrentMenu
, SettingLevel
);
1848 while (ParentMenu
!= NULL
&& !ValidateHiiHandle(ParentMenu
->HiiHandle
)) {
1849 ParentMenu
= UiFindParentMenu(ParentMenu
, SettingLevel
);
1852 if (ParentMenu
!= NULL
) {
1853 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1856 Scope
= FormSetLevel
;
1861 // Form Level Check whether the data is changed.
1863 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1864 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1865 if (!ProcessChangedData(Selection
, gBrowserSettingScope
)) {
1870 if (ParentMenu
!= NULL
) {
1872 // ParentMenu is found. Then, go to it.
1874 if (Scope
== FormLevel
) {
1875 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
1877 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1878 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1879 Selection
->Handle
= ParentMenu
->HiiHandle
;
1882 Selection
->Statement
= NULL
;
1884 Selection
->FormId
= ParentMenu
->FormId
;
1885 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1888 // Clear highlight record for this menu
1890 CurrentMenu
->QuestionId
= 0;
1895 // Current in root page, exit the SendForm
1897 Selection
->Action
= UI_ACTION_EXIT
;
1903 Reconnect the controller.
1905 @param DriverHandle The controller handle which need to be reconnect.
1907 @retval TRUE do the reconnect behavior success.
1908 @retval FALSE do the reconnect behavior failed.
1912 ReconnectController (
1913 IN EFI_HANDLE DriverHandle
1918 Status
= gBS
->DisconnectController(DriverHandle
, NULL
, NULL
);
1919 if (!EFI_ERROR (Status
)) {
1920 Status
= gBS
->ConnectController(DriverHandle
, NULL
, NULL
, TRUE
);
1923 return Status
== EFI_SUCCESS
;
1927 Call the call back function for the question and process the return action.
1929 @param Selection On input, Selection tell setup browser the information
1930 about the Selection, form and formset to be displayed.
1931 On output, Selection return the screen item that is selected
1933 @param FormSet The formset this question belong to.
1934 @param Form The form this question belong to.
1935 @param Question The Question which need to call.
1936 @param Action The action request.
1937 @param SkipSaveOrDiscard Whether skip save or discard action.
1939 @retval EFI_SUCCESS The call back function excutes successfully.
1940 @return Other value if the call back function failed to excute.
1943 ProcessCallBackFunction (
1944 IN OUT UI_MENU_SELECTION
*Selection
,
1945 IN FORM_BROWSER_FORMSET
*FormSet
,
1946 IN FORM_BROWSER_FORM
*Form
,
1947 IN FORM_BROWSER_STATEMENT
*Question
,
1948 IN EFI_BROWSER_ACTION Action
,
1949 IN BOOLEAN SkipSaveOrDiscard
1953 EFI_STATUS InternalStatus
;
1954 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1955 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1956 EFI_HII_VALUE
*HiiValue
;
1957 EFI_IFR_TYPE_VALUE
*TypeValue
;
1958 FORM_BROWSER_STATEMENT
*Statement
;
1959 BOOLEAN SubmitFormIsRequired
;
1960 BOOLEAN DiscardFormIsRequired
;
1963 BROWSER_SETTING_SCOPE SettingLevel
;
1964 EFI_IFR_TYPE_VALUE BackUpValue
;
1965 UINT8
*BackUpBuffer
;
1968 ConfigAccess
= FormSet
->ConfigAccess
;
1969 SubmitFormIsRequired
= FALSE
;
1970 SettingLevel
= FormSetLevel
;
1971 DiscardFormIsRequired
= FALSE
;
1973 Status
= EFI_SUCCESS
;
1974 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1975 BackUpBuffer
= NULL
;
1977 if (ConfigAccess
== NULL
) {
1981 Link
= GetFirstNode (&Form
->StatementListHead
);
1982 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1983 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1984 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1987 // if Question != NULL, only process the question. Else, process all question in this form.
1989 if ((Question
!= NULL
) && (Statement
!= Question
)) {
1993 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
1998 // Check whether Statement is disabled.
2000 if (Statement
->Expression
!= NULL
) {
2001 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
2006 HiiValue
= &Statement
->HiiValue
;
2007 TypeValue
= &HiiValue
->Value
;
2008 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2010 // For OrderedList, passing in the value buffer to Callback()
2012 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2016 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2018 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2019 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2020 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
+ sizeof(CHAR16
), Statement
->BufferValue
);
2021 ASSERT (BackUpBuffer
!= NULL
);
2023 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2027 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2028 Status
= ConfigAccess
->Callback (
2031 Statement
->QuestionId
,
2036 if (!EFI_ERROR (Status
)) {
2038 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2040 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2041 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2042 ASSERT (NewString
!= NULL
);
2044 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2045 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2046 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2048 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2050 FreePool (NewString
);
2054 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2057 case EFI_BROWSER_ACTION_CHANGED
:
2058 switch (ActionRequest
) {
2059 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2060 DiscardFormIsRequired
= TRUE
;
2061 gResetRequired
= TRUE
;
2065 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2066 SubmitFormIsRequired
= TRUE
;
2070 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2071 DiscardFormIsRequired
= TRUE
;
2075 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2076 SubmitFormIsRequired
= TRUE
;
2077 SettingLevel
= FormLevel
;
2081 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2082 DiscardFormIsRequired
= TRUE
;
2083 SettingLevel
= FormLevel
;
2087 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2088 SubmitFormIsRequired
= TRUE
;
2089 SettingLevel
= FormLevel
;
2092 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2093 DiscardFormIsRequired
= TRUE
;
2094 SettingLevel
= FormLevel
;
2097 case EFI_BROWSER_ACTION_REQUEST_RECONNECT
:
2098 gCallbackReconnect
= TRUE
;
2106 case EFI_BROWSER_ACTION_CHANGING
:
2108 // Do the question validation.
2110 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2111 if (!EFI_ERROR (Status
)) {
2113 //check whether the question value changed compared with edit buffer before updating edit buffer
2114 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2116 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2118 // According the spec, return value from call back of "changing" and
2119 // "retrieve" should update to the question's temp buffer.
2121 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2125 case EFI_BROWSER_ACTION_RETRIEVE
:
2127 // According the spec, return value from call back of "changing" and
2128 // "retrieve" should update to the question's temp buffer.
2130 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2138 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2139 // then the browser will use the value passed to Callback() and ignore the
2140 // value returned by Callback().
2142 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2143 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2144 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
+ sizeof(CHAR16
));
2146 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2150 // Do the question validation.
2152 InternalStatus
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2153 if (!EFI_ERROR (InternalStatus
)) {
2155 //check whether the question value changed compared with edit buffer before updating edit buffer
2156 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2158 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2159 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2164 // According the spec, return fail from call back of "changing" and
2165 // "retrieve", should restore the question's value.
2167 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) {
2168 if (Statement
->Storage
!= NULL
) {
2169 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2170 } else if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
2171 ProcessCallBackFunction (Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2175 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2176 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2179 if (Status
== EFI_UNSUPPORTED
) {
2181 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2183 Status
= EFI_SUCCESS
;
2187 if (BackUpBuffer
!= NULL
) {
2188 FreePool (BackUpBuffer
);
2192 // If Question != NULL, means just process one question
2193 // and if code reach here means this question has finished
2194 // processing, so just break.
2196 if (Question
!= NULL
) {
2201 if (gCallbackReconnect
&& (EFI_BROWSER_ACTION_CHANGED
== Action
)) {
2203 // Confirm changes with user first.
2205 if (IsNvUpdateRequiredForFormSet(FormSet
)) {
2206 if (BROWSER_ACTION_DISCARD
== PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES
, NULL
, NULL
, NULL
)) {
2207 gCallbackReconnect
= FALSE
;
2208 DiscardFormIsRequired
= TRUE
;
2210 SubmitFormIsRequired
= TRUE
;
2213 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED
, NULL
, NULL
, NULL
);
2217 // Exit current formset before do the reconnect.
2220 SettingLevel
= FormSetLevel
;
2223 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2224 SubmitForm (FormSet
, Form
, SettingLevel
);
2227 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2228 DiscardForm (FormSet
, Form
, SettingLevel
);
2232 FindNextMenu (Selection
, SettingLevel
);
2239 Call the retrieve type call back function for one question to get the initialize data.
2241 This function only used when in the initialize stage, because in this stage, the
2242 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2244 @param ConfigAccess The config access protocol produced by the hii driver.
2245 @param Statement The Question which need to call.
2246 @param FormSet The formset this question belong to.
2248 @retval EFI_SUCCESS The call back function excutes successfully.
2249 @return Other value if the call back function failed to excute.
2252 ProcessRetrieveForQuestion (
2253 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2254 IN FORM_BROWSER_STATEMENT
*Statement
,
2255 IN FORM_BROWSER_FORMSET
*FormSet
2259 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2260 EFI_HII_VALUE
*HiiValue
;
2261 EFI_IFR_TYPE_VALUE
*TypeValue
;
2264 Status
= EFI_SUCCESS
;
2265 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2267 if (((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) || ConfigAccess
== NULL
) {
2268 return EFI_UNSUPPORTED
;
2271 HiiValue
= &Statement
->HiiValue
;
2272 TypeValue
= &HiiValue
->Value
;
2273 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2275 // For OrderedList, passing in the value buffer to Callback()
2277 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2280 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2281 Status
= ConfigAccess
->Callback (
2283 EFI_BROWSER_ACTION_RETRIEVE
,
2284 Statement
->QuestionId
,
2289 if (!EFI_ERROR (Status
) && HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2290 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2291 ASSERT (NewString
!= NULL
);
2293 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2294 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2295 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2297 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2299 FreePool (NewString
);
2306 The worker function that send the displays to the screen. On output,
2307 the selection made by user is returned.
2309 @param Selection On input, Selection tell setup browser the information
2310 about the Selection, form and formset to be displayed.
2311 On output, Selection return the screen item that is selected
2314 @retval EFI_SUCCESS The page is displayed successfully.
2315 @return Other value if the page failed to be diplayed.
2320 IN OUT UI_MENU_SELECTION
*Selection
2325 EFI_HANDLE NotifyHandle
;
2326 FORM_BROWSER_STATEMENT
*Statement
;
2327 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2329 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2332 // Register notify for Form package update
2334 Status
= mHiiDatabase
->RegisterPackageNotify (
2336 EFI_HII_PACKAGE_FORMS
,
2339 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2342 if (EFI_ERROR (Status
)) {
2347 // Initialize current settings of Questions in this FormSet
2349 InitializeCurrentSetting (Selection
->FormSet
);
2352 // Initilize Action field.
2354 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2357 // Clean the mCurFakeQestId value is formset refreshed.
2363 // IFR is updated, force to reparse the IFR binary
2364 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and
2365 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.
2367 if (mHiiPackageListUpdated
) {
2368 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2369 mHiiPackageListUpdated
= FALSE
;
2374 // Initialize Selection->Form
2376 if (Selection
->FormId
== 0) {
2378 // Zero FormId indicates display the first Form in a FormSet
2380 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2382 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2383 Selection
->FormId
= Selection
->Form
->FormId
;
2385 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2388 if (Selection
->Form
== NULL
) {
2390 // No Form to display
2392 Status
= EFI_NOT_FOUND
;
2397 // Check Form is suppressed.
2399 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2400 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2402 // Form is suppressed.
2404 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
2405 Status
= EFI_NOT_FOUND
;
2411 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2412 // for each question with callback flag.
2413 // New form may be the first form, or the different form after another form close.
2415 if (((Selection
->Handle
!= mCurrentHiiHandle
) ||
2416 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2417 (Selection
->FormId
!= mCurrentFormId
))) {
2419 // Update Retrieve flag.
2421 mFinishRetrieveCall
= FALSE
;
2424 // Keep current form information
2426 mCurrentHiiHandle
= Selection
->Handle
;
2427 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2428 mCurrentFormId
= Selection
->FormId
;
2430 if (ConfigAccess
!= NULL
) {
2431 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2432 if (EFI_ERROR (Status
)) {
2437 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2439 if (mHiiPackageListUpdated
) {
2440 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2441 mHiiPackageListUpdated
= FALSE
;
2448 // Load Questions' Value for display
2450 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2451 if (EFI_ERROR (Status
)) {
2455 if (!mFinishRetrieveCall
) {
2457 // Finish call RETRIEVE callback for this form.
2459 mFinishRetrieveCall
= TRUE
;
2461 if (ConfigAccess
!= NULL
) {
2462 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2463 if (EFI_ERROR (Status
)) {
2468 // IFR is updated during callback of open form, force to reparse the IFR binary
2470 if (mHiiPackageListUpdated
) {
2471 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2472 mHiiPackageListUpdated
= FALSE
;
2481 Status
= DisplayForm ();
2482 if (EFI_ERROR (Status
)) {
2487 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2489 Statement
= Selection
->Statement
;
2490 if (Statement
!= NULL
) {
2491 if ((ConfigAccess
!= NULL
) &&
2492 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2493 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2494 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2495 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2497 // Process dynamic update ref opcode.
2499 if (!EFI_ERROR (Status
)) {
2500 Status
= ProcessGotoOpCode(Statement
, Selection
);
2504 // Callback return error status or status return from process goto opcode.
2506 if (EFI_ERROR (Status
)) {
2508 // Cross reference will not be taken
2510 Selection
->FormId
= Selection
->Form
->FormId
;
2511 Selection
->QuestionId
= 0;
2516 if (!EFI_ERROR (Status
) &&
2517 (Statement
->Operand
!= EFI_IFR_REF_OP
) &&
2518 ((Statement
->Storage
== NULL
) || (Statement
->Storage
!= NULL
&& Statement
->ValueChanged
))) {
2520 // Only question value has been changed, browser will trig CHANGED callback.
2522 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2524 //check whether the question value changed compared with buffer value
2525 //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen
2527 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2531 // Do the question validation.
2533 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2534 if (!EFI_ERROR (Status
) && (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2535 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2537 // Verify whether question value has checked, update the ValueChanged flag in Question.
2539 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2544 // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage
2545 // and process question success till here, trig the gResetFlag/gFlagReconnect.
2547 if ((Status
== EFI_SUCCESS
) &&
2548 (Statement
->Storage
== NULL
)) {
2549 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2550 gResetRequired
= TRUE
;
2553 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2554 gFlagReconnect
= TRUE
;
2560 // Check whether Exit flag is TRUE.
2562 if (gExitRequired
) {
2563 switch (gBrowserSettingScope
) {
2565 Selection
->Action
= UI_ACTION_EXIT
;
2570 FindNextMenu (Selection
, gBrowserSettingScope
);
2577 gExitRequired
= FALSE
;
2581 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2582 // for each question with callback flag.
2584 if ((ConfigAccess
!= NULL
) &&
2585 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2586 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2587 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2588 (Selection
->FormId
!= mCurrentFormId
))) {
2590 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2591 if (EFI_ERROR (Status
)) {
2595 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2599 // Reset current form information to the initial setting when error happens or form exit.
2601 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2602 mCurrentHiiHandle
= NULL
;
2603 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2608 // Unregister notify for Form package update
2610 mHiiDatabase
->UnregisterPackageNotify (