2 Utility functions for UI presentation.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 BOOLEAN mHiiPackageListUpdated
;
19 UI_MENU_SELECTION
*gCurrentSelection
;
20 EFI_HII_HANDLE mCurrentHiiHandle
= NULL
;
21 EFI_GUID mCurrentFormSetGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
22 UINT16 mCurrentFormId
= 0;
23 EFI_EVENT mValueChangedEvent
= NULL
;
24 LIST_ENTRY mRefreshEventList
= INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList
);
25 UINT16 mCurFakeQestId
;
26 FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
27 BOOLEAN mFinishRetrieveCall
= FALSE
;
30 Evaluate all expressions in a Form.
32 @param FormSet FormSet this Form belongs to.
35 @retval EFI_SUCCESS The expression evaluated successfuly
39 EvaluateFormExpressions (
40 IN FORM_BROWSER_FORMSET
*FormSet
,
41 IN FORM_BROWSER_FORM
*Form
46 FORM_EXPRESSION
*Expression
;
48 Link
= GetFirstNode (&Form
->ExpressionListHead
);
49 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
50 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
51 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
53 if (Expression
->Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
||
54 Expression
->Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
||
55 Expression
->Type
== EFI_HII_EXPRESSION_WARNING_IF
||
56 Expression
->Type
== EFI_HII_EXPRESSION_WRITE
||
57 (Expression
->Type
== EFI_HII_EXPRESSION_READ
&& Form
->FormType
!= STANDARD_MAP_FORM_TYPE
)) {
59 // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
64 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
65 if (EFI_ERROR (Status
)) {
74 Base on the opcode buffer info to get the display statement.
76 @param OpCode The input opcode buffer for this statement.
78 @retval Statement The statement use this opcode buffer.
81 FORM_DISPLAY_ENGINE_STATEMENT
*
83 IN EFI_IFR_OP_HEADER
*OpCode
86 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
89 Link
= GetFirstNode (&gDisplayFormData
.StatementListHead
);
90 while (!IsNull (&gDisplayFormData
.StatementListHead
, Link
)) {
91 DisplayStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
93 if (DisplayStatement
->OpCode
== OpCode
) {
94 return DisplayStatement
;
96 Link
= GetNextNode (&gDisplayFormData
.StatementListHead
, Link
);
103 Free the refresh event list.
112 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
114 while (!IsListEmpty (&mRefreshEventList
)) {
115 Link
= GetFirstNode (&mRefreshEventList
);
116 EventNode
= FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link
);
117 RemoveEntryList (&EventNode
->Link
);
119 gBS
->CloseEvent (EventNode
->RefreshEvent
);
121 FreePool (EventNode
);
126 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
129 @param Statement The statement need to check.
134 IN OUT FORM_BROWSER_STATEMENT
*Statement
137 GetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
140 // Reset FormPackage update flag
142 mHiiPackageListUpdated
= FALSE
;
145 // Question value may be changed, need invoke its Callback()
147 ProcessCallBackFunction (gCurrentSelection
, gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
149 if (mHiiPackageListUpdated
) {
151 // Package list is updated, force to reparse IFR binary of target Formset
153 mHiiPackageListUpdated
= FALSE
;
154 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
159 Refresh the question which has refresh guid event attribute.
161 @param Event The event which has this function related.
162 @param Context The input context info related to this event or the status code return to the caller.
166 RefreshEventNotifyForStatement(
171 FORM_BROWSER_STATEMENT
*Statement
;
173 Statement
= (FORM_BROWSER_STATEMENT
*)Context
;
174 UpdateStatement(Statement
);
175 gBS
->SignalEvent (mValueChangedEvent
);
179 Refresh the questions within this form.
181 @param Event The event which has this function related.
182 @param Context The input context info related to this event or the status code return to the caller.
186 RefreshEventNotifyForForm(
191 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
193 gBS
->SignalEvent (mValueChangedEvent
);
197 Create refresh hook event for statement which has refresh event or interval.
199 @param Statement The statement need to check.
203 CreateRefreshEventForStatement (
204 IN FORM_BROWSER_STATEMENT
*Statement
208 EFI_EVENT RefreshEvent
;
209 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
212 // If question has refresh guid, create the notify function.
214 Status
= gBS
->CreateEventEx (
217 RefreshEventNotifyForStatement
,
219 &Statement
->RefreshGuid
,
221 ASSERT_EFI_ERROR (Status
);
223 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
224 ASSERT (EventNode
!= NULL
);
225 EventNode
->RefreshEvent
= RefreshEvent
;
226 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
230 Create refresh hook event for form which has refresh event or interval.
232 @param Form The form need to check.
236 CreateRefreshEventForForm (
237 IN FORM_BROWSER_FORM
*Form
241 EFI_EVENT RefreshEvent
;
242 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
245 // If question has refresh guid, create the notify function.
247 Status
= gBS
->CreateEventEx (
250 RefreshEventNotifyForForm
,
254 ASSERT_EFI_ERROR (Status
);
256 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
257 ASSERT (EventNode
!= NULL
);
258 EventNode
->RefreshEvent
= RefreshEvent
;
259 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
264 Initialize the Display statement structure data.
266 @param DisplayStatement Pointer to the display Statement data strucure.
267 @param Statement The statement need to check.
270 InitializeDisplayStatement (
271 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
272 IN FORM_BROWSER_STATEMENT
*Statement
276 QUESTION_OPTION
*Option
;
277 DISPLAY_QUESTION_OPTION
*DisplayOption
;
278 FORM_DISPLAY_ENGINE_STATEMENT
*ParentStatement
;
280 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
281 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
282 DisplayStatement
->OpCode
= Statement
->OpCode
;
283 InitializeListHead (&DisplayStatement
->NestStatementList
);
284 InitializeListHead (&DisplayStatement
->OptionListHead
);
286 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
287 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
289 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
290 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
294 // Initilize the option list in statement.
296 Link
= GetFirstNode (&Statement
->OptionListHead
);
297 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
298 Option
= QUESTION_OPTION_FROM_LINK (Link
);
299 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
300 if ((Option
->SuppressExpression
!= NULL
) &&
301 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
305 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
306 ASSERT (DisplayOption
!= NULL
);
308 DisplayOption
->ImageId
= Option
->ImageId
;
309 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
310 DisplayOption
->OptionOpCode
= Option
->OpCode
;
311 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
314 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
317 // Some special op code need an extra buffer to save the data.
318 // Such as string, password, orderedlist...
320 if (Statement
->BufferValue
!= NULL
) {
322 // Ordered list opcode may not initilized, get default value here.
324 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
325 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
328 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
329 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
332 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
335 // Get the highlight statement for current form.
337 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
338 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
339 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
343 // Create the refresh event process function.
345 if (!IsZeroGuid (&Statement
->RefreshGuid
)) {
346 CreateRefreshEventForStatement (Statement
);
350 // For RTC type of date/time, set default refresh interval to be 1 second.
352 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
353 Statement
->RefreshInterval
= 1;
357 // Create the refresh guid hook event.
358 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
360 if ((!IsZeroGuid (&Statement
->RefreshGuid
)) || (Statement
->RefreshInterval
!= 0)) {
361 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
365 // Save the password check function for later use.
367 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
368 DisplayStatement
->PasswordCheck
= PasswordCheck
;
372 // If this statement is nest in the subtitle, insert to the host statement.
373 // else insert to the form it belongs to.
375 if (Statement
->ParentStatement
!= NULL
) {
376 ParentStatement
= GetDisplayStatement(Statement
->ParentStatement
->OpCode
);
377 ASSERT (ParentStatement
!= NULL
);
378 InsertTailList(&ParentStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
380 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
385 Process for the refresh interval statement.
387 @param Event The Event need to be process
388 @param Context The context of the event.
393 RefreshIntervalProcess (
398 FORM_BROWSER_STATEMENT
*Statement
;
401 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
402 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
403 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
404 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
406 if (Statement
->RefreshInterval
== 0) {
410 UpdateStatement(Statement
);
413 gBS
->SignalEvent (mValueChangedEvent
);
418 Make a copy of the global hotkey info.
426 BROWSER_HOT_KEY
*HotKey
;
427 BROWSER_HOT_KEY
*CopyKey
;
430 Link
= GetFirstNode (&gBrowserHotKeyList
);
431 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
432 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
434 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
435 ASSERT (CopyKey
!= NULL
);
436 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
437 ASSERT (CopyKey
->KeyData
!= NULL
);
438 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
439 ASSERT (CopyKey
->HelpString
!= NULL
);
441 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
443 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
449 Get the extra question attribute from override question list.
451 @param QuestionId The question id for this request question.
453 @retval The attribute for this question or NULL if not found this
454 question in the list.
458 ProcessQuestionExtraAttr (
459 IN EFI_QUESTION_ID QuestionId
463 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
466 // Return HII_DISPLAY_NONE if input a invalid question id.
468 if (QuestionId
== 0) {
469 return HII_DISPLAY_NONE
;
472 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
473 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
474 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
475 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
477 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
478 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
479 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
480 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
481 return QuestionDesc
->Attribute
;
485 return HII_DISPLAY_NONE
;
490 Enum all statement in current form, find all the statement can be display and
491 add to the display form.
495 AddStatementToDisplayForm (
501 FORM_BROWSER_STATEMENT
*Statement
;
502 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
503 UINT8 MinRefreshInterval
;
504 EFI_EVENT RefreshIntervalEvent
;
505 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
506 BOOLEAN FormEditable
;
507 UINT32 ExtraAttribute
;
509 MinRefreshInterval
= 0;
510 FormEditable
= FALSE
;
513 // Process the statement outside the form, these statements are not recognized
516 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
517 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
518 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
519 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
521 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
522 ASSERT (DisplayStatement
!= NULL
);
523 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
524 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
525 DisplayStatement
->OpCode
= Statement
->OpCode
;
527 InitializeListHead (&DisplayStatement
->NestStatementList
);
528 InitializeListHead (&DisplayStatement
->OptionListHead
);
530 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
534 // treat formset as statement outside the form,get its opcode.
536 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
537 ASSERT (DisplayStatement
!= NULL
);
539 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
540 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
541 DisplayStatement
->OpCode
= gCurrentSelection
->FormSet
->OpCode
;
543 InitializeListHead (&DisplayStatement
->NestStatementList
);
544 InitializeListHead (&DisplayStatement
->OptionListHead
);
546 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 (!IsZeroGuid (&gCurrentSelection
->Form
->RefreshGuid
)) {
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 EfiEventEmptyFunction
,
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 gResetRequiredFormLevel
= TRUE
;
1001 gResetRequiredSystemLevel
= TRUE
;
1004 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1006 // Form Exit without saving, Similar to ESC Key.
1007 // FormSet Exit without saving, Exit SendForm.
1008 // System Exit without saving, CallExitHandler and Exit SendForm.
1010 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1011 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1012 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1013 } else if (gBrowserSettingScope
== SystemLevel
) {
1014 if (ExitHandlerFunction
!= NULL
) {
1015 ExitHandlerFunction ();
1017 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1025 Check whether the formset guid is in this Hii package list.
1027 @param HiiHandle The HiiHandle for this HII package list.
1028 @param FormSetGuid The formset guid for the request formset.
1030 @retval TRUE Find the formset guid.
1031 @retval FALSE Not found the formset guid.
1035 GetFormsetGuidFromHiiHandle (
1036 IN EFI_HII_HANDLE HiiHandle
,
1037 IN EFI_GUID
*FormSetGuid
1040 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1044 UINT32 PackageListLength
;
1045 EFI_HII_PACKAGE_HEADER PackageHeader
;
1052 HiiPackageList
= NULL
;
1055 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1056 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1057 HiiPackageList
= AllocatePool (BufferSize
);
1058 ASSERT (HiiPackageList
!= NULL
);
1060 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1062 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1067 // Get Form package from this HII package List
1069 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1071 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1073 while (Offset
< PackageListLength
) {
1074 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1075 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1076 Offset
+= PackageHeader
.Length
;
1078 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1080 // Search FormSet in this Form Package
1082 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1083 while (Offset2
< PackageHeader
.Length
) {
1084 OpCodeData
= Package
+ Offset2
;
1086 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1087 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1093 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1101 FreePool (HiiPackageList
);
1107 Find HII Handle in the HII database associated with given Device Path.
1109 If DevicePath is NULL, then ASSERT.
1111 @param DevicePath Device Path associated with the HII package list
1113 @param FormsetGuid The formset guid for this formset.
1115 @retval Handle HII package list Handle associated with the Device
1117 @retval NULL Hii Package list handle is not found.
1121 DevicePathToHiiHandle (
1122 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1123 IN EFI_GUID
*FormsetGuid
1127 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1130 EFI_HANDLE DriverHandle
;
1131 EFI_HII_HANDLE
*HiiHandles
;
1132 EFI_HII_HANDLE HiiHandle
;
1134 ASSERT (DevicePath
!= NULL
);
1136 TmpDevicePath
= DevicePath
;
1138 // Locate Device Path Protocol handle buffer
1140 Status
= gBS
->LocateDevicePath (
1141 &gEfiDevicePathProtocolGuid
,
1145 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1150 // Retrieve all HII Handles from HII database
1152 HiiHandles
= HiiGetHiiHandles (NULL
);
1153 if (HiiHandles
== NULL
) {
1158 // Search Hii Handle by Driver Handle
1161 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1162 Status
= mHiiDatabase
->GetPackageListHandle (
1167 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1168 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1169 HiiHandle
= HiiHandles
[Index
];
1173 if (HiiHandle
!= NULL
) {
1179 FreePool (HiiHandles
);
1184 Find HII Handle in the HII database associated with given form set guid.
1186 If FormSetGuid is NULL, then ASSERT.
1188 @param ComparingGuid FormSet Guid associated with the HII package list
1191 @retval Handle HII package list Handle associated with the Device
1193 @retval NULL Hii Package list handle is not found.
1197 FormSetGuidToHiiHandle (
1198 EFI_GUID
*ComparingGuid
1201 EFI_HII_HANDLE
*HiiHandles
;
1202 EFI_HII_HANDLE HiiHandle
;
1205 ASSERT (ComparingGuid
!= NULL
);
1209 // Get all the Hii handles
1211 HiiHandles
= HiiGetHiiHandles (NULL
);
1212 ASSERT (HiiHandles
!= NULL
);
1215 // Search for formset of each class type
1217 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1218 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1219 HiiHandle
= HiiHandles
[Index
];
1223 if (HiiHandle
!= NULL
) {
1228 FreePool (HiiHandles
);
1234 check how to process the changed data in current form or form set.
1236 @param Selection On input, Selection tell setup browser the information
1237 about the Selection, form and formset to be displayed.
1238 On output, Selection return the screen item that is selected
1241 @param Scope Data save or discard scope, form or formset.
1243 @retval TRUE Success process the changed data, will return to the parent form.
1244 @retval FALSE Reject to process the changed data, will stay at current form.
1247 ProcessChangedData (
1248 IN OUT UI_MENU_SELECTION
*Selection
,
1249 IN BROWSER_SETTING_SCOPE Scope
1256 switch (mFormDisplay
->ConfirmDataChange()) {
1257 case BROWSER_ACTION_DISCARD
:
1258 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1261 case BROWSER_ACTION_SUBMIT
:
1262 Status
= SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1263 if (EFI_ERROR (Status
)) {
1268 case BROWSER_ACTION_NONE
:
1274 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1284 Find parent formset menu(the first menu which has different formset) for current menu.
1285 If not find, just return to the first menu.
1287 @param Selection The selection info.
1292 IN OUT UI_MENU_SELECTION
*Selection
1295 FORM_ENTRY_INFO
*CurrentMenu
;
1296 FORM_ENTRY_INFO
*ParentMenu
;
1298 CurrentMenu
= Selection
->CurrentMenu
;
1299 ParentMenu
= UiFindParentMenu(CurrentMenu
, FormSetLevel
);
1301 if (ParentMenu
!= NULL
) {
1302 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1303 Selection
->Handle
= ParentMenu
->HiiHandle
;
1304 Selection
->FormId
= ParentMenu
->FormId
;
1305 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1307 Selection
->FormId
= CurrentMenu
->FormId
;
1308 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1311 Selection
->Statement
= NULL
;
1315 Process the goto op code, update the info in the selection structure.
1317 @param Statement The statement belong to goto op code.
1318 @param Selection The selection info.
1320 @retval EFI_SUCCESS The menu process successfully.
1321 @return Other value if the process failed.
1325 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1326 IN OUT UI_MENU_SELECTION
*Selection
1330 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1331 FORM_BROWSER_FORM
*RefForm
;
1333 EFI_HII_HANDLE HiiHandle
;
1335 Status
= EFI_SUCCESS
;
1340 // Prepare the device path check, get the device path info first.
1342 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1343 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1347 // Check whether the device path string is a valid string.
1349 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1350 if (Selection
->Form
->ModalForm
) {
1355 // Goto another Hii Package list
1357 if (mPathFromText
!= NULL
) {
1358 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1359 if (DevicePath
!= NULL
) {
1360 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1361 FreePool (DevicePath
);
1363 FreePool (StringPtr
);
1366 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1368 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND
, NULL
, NULL
, NULL
);
1369 FreePool (StringPtr
);
1373 if (HiiHandle
!= Selection
->Handle
) {
1375 // Goto another Formset, check for uncommitted data
1377 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1378 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1379 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1385 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1386 Selection
->Handle
= HiiHandle
;
1387 if (Selection
->Handle
== NULL
) {
1389 // If target Hii Handle not found, exit current formset.
1391 FindParentFormSet(Selection
);
1395 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1396 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1397 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1398 } else if (!IsZeroGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
)) {
1399 if (Selection
->Form
->ModalForm
) {
1402 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1404 // Goto another Formset, check for uncommitted data
1406 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1407 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1408 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1414 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1415 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1416 if (Selection
->Handle
== NULL
) {
1418 // If target Hii Handle not found, exit current formset.
1420 FindParentFormSet(Selection
);
1424 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1425 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1426 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1427 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1429 // Goto another Form, check for uncommitted data
1431 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1432 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1433 if (!ProcessChangedData (Selection
, FormLevel
)) {
1439 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1440 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1441 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1443 // Form is suppressed.
1445 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
1450 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1451 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1452 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1453 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1461 Process Question Config.
1463 @param Selection The UI menu selection.
1464 @param Question The Question to be peocessed.
1466 @retval EFI_SUCCESS Question Config process success.
1467 @retval Other Question Config process fail.
1471 ProcessQuestionConfig (
1472 IN UI_MENU_SELECTION
*Selection
,
1473 IN FORM_BROWSER_STATEMENT
*Question
1480 if (Question
->QuestionConfig
== 0) {
1487 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1488 if (ConfigResp
== NULL
) {
1489 return EFI_NOT_FOUND
;
1490 } else if (ConfigResp
[0] == L
'\0') {
1495 // Send config to Configuration Driver
1497 Status
= mHiiConfigRouting
->RouteConfig (
1508 Process the user input data.
1510 @param UserInput The user input data.
1512 @retval EFI_SUCESSS This function always return successfully for now.
1517 IN USER_INPUT
*UserInput
1521 FORM_BROWSER_STATEMENT
*Statement
;
1523 Status
= EFI_SUCCESS
;
1527 // When Exit from FormDisplay function, one of the below two cases must be true.
1529 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1532 // Remove the last highligh question id, this id will update when show next form.
1534 gCurrentSelection
->QuestionId
= 0;
1535 if (UserInput
->SelectedStatement
!= NULL
){
1536 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1537 ASSERT (Statement
!= NULL
);
1540 // This question is the current user select one,record it and later
1541 // show it as the highlight question.
1543 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1545 // For statement like text, actio, it not has question id.
1546 // So use FakeQuestionId to save the question.
1548 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1549 mCurFakeQestId
= Statement
->FakeQuestionId
;
1556 // First process the Action field in USER_INPUT.
1558 if (UserInput
->Action
!= 0) {
1559 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1560 gCurrentSelection
->Statement
= NULL
;
1562 ASSERT (Statement
!= NULL
);
1563 gCurrentSelection
->Statement
= Statement
;
1564 switch (Statement
->Operand
) {
1565 case EFI_IFR_REF_OP
:
1566 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1569 case EFI_IFR_ACTION_OP
:
1571 // Process the Config string <ConfigResp>
1573 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1576 case EFI_IFR_RESET_BUTTON_OP
:
1578 // Reset Question to default value specified by DefaultId
1580 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1581 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1585 switch (Statement
->Operand
) {
1586 case EFI_IFR_STRING_OP
:
1587 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1588 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1589 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1590 FreePool (UserInput
->InputValue
.Buffer
);
1593 case EFI_IFR_PASSWORD_OP
:
1594 if (UserInput
->InputValue
.Buffer
== NULL
) {
1596 // User not input new password, just return.
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 ZeroMem (UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1605 FreePool (UserInput
->InputValue
.Buffer
);
1607 // Two password match, send it to Configuration Driver
1609 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1610 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1612 // Clean the value after saved it.
1614 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1615 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1617 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1621 case EFI_IFR_ORDERED_LIST_OP
:
1622 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1626 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1638 Display form and wait for user to select one menu option, then return it.
1640 @retval EFI_SUCESSS This function always return successfully for now.
1649 USER_INPUT UserInput
;
1650 FORM_ENTRY_INFO
*CurrentMenu
;
1652 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1655 // Update the menu history data.
1657 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1658 if (CurrentMenu
== NULL
) {
1660 // Current menu not found, add it to the menu tree
1662 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1663 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1664 ASSERT (CurrentMenu
!= NULL
);
1668 // Back up the form view history data for this form.
1670 UiCopyMenuList(&gCurrentSelection
->Form
->FormViewListHead
, &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
1672 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1674 if (gCurrentSelection
->QuestionId
== 0) {
1676 // Highlight not specified, fetch it from cached menu
1678 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1681 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1682 if (EFI_ERROR (Status
)) {
1686 UpdateDisplayFormData ();
1688 ASSERT (gDisplayFormData
.BrowserStatus
== BROWSER_SUCCESS
);
1689 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1690 if (EFI_ERROR (Status
)) {
1691 FreeDisplayFormData();
1695 Status
= ProcessUserInput (&UserInput
);
1696 FreeDisplayFormData();
1701 Functions which are registered to receive notification of
1702 database events have this prototype. The actual event is encoded
1703 in NotifyType. The following table describes how PackageType,
1704 PackageGuid, Handle, and Package are used for each of the
1707 @param PackageType Package type of the notification.
1709 @param PackageGuid If PackageType is
1710 EFI_HII_PACKAGE_TYPE_GUID, then this is
1711 the pointer to the GUID from the Guid
1712 field of EFI_HII_PACKAGE_GUID_HEADER.
1713 Otherwise, it must be NULL.
1715 @param Package Points to the package referred to by the
1716 notification Handle The handle of the package
1717 list which contains the specified package.
1719 @param Handle The HII handle.
1721 @param NotifyType The type of change concerning the
1723 EFI_HII_DATABASE_NOTIFY_TYPE.
1729 IN UINT8 PackageType
,
1730 IN CONST EFI_GUID
*PackageGuid
,
1731 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1732 IN EFI_HII_HANDLE Handle
,
1733 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1736 mHiiPackageListUpdated
= TRUE
;
1742 Update the NV flag info for this form set.
1744 @param FormSet FormSet data structure.
1748 IsNvUpdateRequiredForFormSet (
1749 IN FORM_BROWSER_FORMSET
*FormSet
1753 FORM_BROWSER_FORM
*Form
;
1757 // Not finished question initialization, return FALSE.
1759 if (!FormSet
->QuestionInited
) {
1765 Link
= GetFirstNode (&FormSet
->FormListHead
);
1766 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1767 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1769 RetVal
= IsNvUpdateRequiredForForm(Form
);
1774 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1781 Update the NvUpdateRequired flag for a form.
1783 @param Form Form data structure.
1787 IsNvUpdateRequiredForForm (
1788 IN FORM_BROWSER_FORM
*Form
1792 FORM_BROWSER_STATEMENT
*Statement
;
1794 Link
= GetFirstNode (&Form
->StatementListHead
);
1795 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1796 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1798 if (Statement
->ValueChanged
) {
1802 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1809 Find menu which will show next time.
1811 @param Selection On input, Selection tell setup browser the information
1812 about the Selection, form and formset to be displayed.
1813 On output, Selection return the screen item that is selected
1815 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1816 else, we need to exit current formset.
1818 @retval TRUE Exit current form.
1819 @retval FALSE User press ESC and keep in current form.
1823 IN OUT UI_MENU_SELECTION
*Selection
,
1824 IN BROWSER_SETTING_SCOPE SettingLevel
1827 FORM_ENTRY_INFO
*CurrentMenu
;
1828 FORM_ENTRY_INFO
*ParentMenu
;
1829 BROWSER_SETTING_SCOPE Scope
;
1831 CurrentMenu
= Selection
->CurrentMenu
;
1832 Scope
= FormSetLevel
;
1834 ParentMenu
= UiFindParentMenu(CurrentMenu
, SettingLevel
);
1835 while (ParentMenu
!= NULL
&& !ValidateHiiHandle(ParentMenu
->HiiHandle
)) {
1836 ParentMenu
= UiFindParentMenu(ParentMenu
, SettingLevel
);
1839 if (ParentMenu
!= NULL
) {
1840 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1843 Scope
= FormSetLevel
;
1848 // Form Level Check whether the data is changed.
1850 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1851 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1852 if (!ProcessChangedData(Selection
, gBrowserSettingScope
)) {
1857 if (ParentMenu
!= NULL
) {
1859 // ParentMenu is found. Then, go to it.
1861 if (Scope
== FormLevel
) {
1862 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
1864 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1865 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1866 Selection
->Handle
= ParentMenu
->HiiHandle
;
1869 Selection
->Statement
= NULL
;
1871 Selection
->FormId
= ParentMenu
->FormId
;
1872 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1875 // Clear highlight record for this menu
1877 CurrentMenu
->QuestionId
= 0;
1882 // Current in root page, exit the SendForm
1884 Selection
->Action
= UI_ACTION_EXIT
;
1890 Reconnect the controller.
1892 @param DriverHandle The controller handle which need to be reconnect.
1894 @retval TRUE do the reconnect behavior success.
1895 @retval FALSE do the reconnect behavior failed.
1899 ReconnectController (
1900 IN EFI_HANDLE DriverHandle
1905 Status
= gBS
->DisconnectController(DriverHandle
, NULL
, NULL
);
1906 if (!EFI_ERROR (Status
)) {
1907 Status
= gBS
->ConnectController(DriverHandle
, NULL
, NULL
, TRUE
);
1910 return Status
== EFI_SUCCESS
;
1914 Call the call back function for the question and process the return action.
1916 @param Selection On input, Selection tell setup browser the information
1917 about the Selection, form and formset to be displayed.
1918 On output, Selection return the screen item that is selected
1920 @param FormSet The formset this question belong to.
1921 @param Form The form this question belong to.
1922 @param Question The Question which need to call.
1923 @param Action The action request.
1924 @param SkipSaveOrDiscard Whether skip save or discard action.
1926 @retval EFI_SUCCESS The call back function executes successfully.
1927 @return Other value if the call back function failed to execute.
1930 ProcessCallBackFunction (
1931 IN OUT UI_MENU_SELECTION
*Selection
,
1932 IN FORM_BROWSER_FORMSET
*FormSet
,
1933 IN FORM_BROWSER_FORM
*Form
,
1934 IN FORM_BROWSER_STATEMENT
*Question
,
1935 IN EFI_BROWSER_ACTION Action
,
1936 IN BOOLEAN SkipSaveOrDiscard
1940 EFI_STATUS InternalStatus
;
1941 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1942 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1943 EFI_HII_VALUE
*HiiValue
;
1944 EFI_IFR_TYPE_VALUE
*TypeValue
;
1945 FORM_BROWSER_STATEMENT
*Statement
;
1946 BOOLEAN SubmitFormIsRequired
;
1947 BOOLEAN DiscardFormIsRequired
;
1950 BROWSER_SETTING_SCOPE SettingLevel
;
1951 EFI_IFR_TYPE_VALUE BackUpValue
;
1952 UINT8
*BackUpBuffer
;
1955 ConfigAccess
= FormSet
->ConfigAccess
;
1956 SubmitFormIsRequired
= FALSE
;
1957 SettingLevel
= FormSetLevel
;
1958 DiscardFormIsRequired
= FALSE
;
1960 Status
= EFI_SUCCESS
;
1961 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1962 BackUpBuffer
= NULL
;
1964 if (ConfigAccess
== NULL
) {
1968 Link
= GetFirstNode (&Form
->StatementListHead
);
1969 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1970 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1971 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1974 // if Question != NULL, only process the question. Else, process all question in this form.
1976 if ((Question
!= NULL
) && (Statement
!= Question
)) {
1980 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
1985 // Check whether Statement is disabled.
1987 if (Statement
->Expression
!= NULL
) {
1988 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
1993 HiiValue
= &Statement
->HiiValue
;
1994 TypeValue
= &HiiValue
->Value
;
1995 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
1997 // For OrderedList, passing in the value buffer to Callback()
1999 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2003 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2005 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2006 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2007 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
, Statement
->BufferValue
);
2008 ASSERT (BackUpBuffer
!= NULL
);
2010 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2014 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2015 Status
= ConfigAccess
->Callback (
2018 Statement
->QuestionId
,
2023 if (!EFI_ERROR (Status
)) {
2025 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2027 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2028 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2029 ASSERT (NewString
!= NULL
);
2031 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2032 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2033 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2034 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2036 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2038 FreePool (NewString
);
2042 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2045 case EFI_BROWSER_ACTION_CHANGED
:
2046 switch (ActionRequest
) {
2047 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2048 DiscardFormIsRequired
= TRUE
;
2049 gResetRequiredFormLevel
= TRUE
;
2050 gResetRequiredSystemLevel
= TRUE
;
2054 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2055 SubmitFormIsRequired
= TRUE
;
2059 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2060 DiscardFormIsRequired
= TRUE
;
2064 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2065 SubmitFormIsRequired
= TRUE
;
2066 SettingLevel
= FormLevel
;
2070 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2071 DiscardFormIsRequired
= TRUE
;
2072 SettingLevel
= FormLevel
;
2076 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2077 SubmitFormIsRequired
= TRUE
;
2078 SettingLevel
= FormLevel
;
2081 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2082 DiscardFormIsRequired
= TRUE
;
2083 SettingLevel
= FormLevel
;
2086 case EFI_BROWSER_ACTION_REQUEST_RECONNECT
:
2087 gCallbackReconnect
= TRUE
;
2095 case EFI_BROWSER_ACTION_CHANGING
:
2097 // Do the question validation.
2099 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2100 if (!EFI_ERROR (Status
)) {
2102 //check whether the question value changed compared with edit buffer before updating edit buffer
2103 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2105 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2107 // According the spec, return value from call back of "changing" and
2108 // "retrieve" should update to the question's temp buffer.
2110 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2114 case EFI_BROWSER_ACTION_RETRIEVE
:
2116 // According the spec, return value from call back of "changing" and
2117 // "retrieve" should update to the question's temp buffer.
2119 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2127 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2128 // then the browser will use the value passed to Callback() and ignore the
2129 // value returned by Callback().
2131 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2132 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2133 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
);
2135 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2139 // Do the question validation.
2141 InternalStatus
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2142 if (!EFI_ERROR (InternalStatus
)) {
2144 //check whether the question value changed compared with edit buffer before updating edit buffer
2145 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2147 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2148 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2153 // According the spec, return fail from call back of "changing" and
2154 // "retrieve", should restore the question's value.
2156 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) {
2157 if (Statement
->Storage
!= NULL
) {
2158 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2159 } else if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
2160 ProcessCallBackFunction (Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2164 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2165 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2168 if (Status
== EFI_UNSUPPORTED
) {
2170 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2172 Status
= EFI_SUCCESS
;
2176 if (BackUpBuffer
!= NULL
) {
2177 FreePool (BackUpBuffer
);
2181 // If Question != NULL, means just process one question
2182 // and if code reach here means this question has finished
2183 // processing, so just break.
2185 if (Question
!= NULL
) {
2190 if (gCallbackReconnect
&& (EFI_BROWSER_ACTION_CHANGED
== Action
)) {
2192 // Confirm changes with user first.
2194 if (IsNvUpdateRequiredForFormSet(FormSet
)) {
2195 if (BROWSER_ACTION_DISCARD
== PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES
, NULL
, NULL
, NULL
)) {
2196 gCallbackReconnect
= FALSE
;
2197 DiscardFormIsRequired
= TRUE
;
2199 SubmitFormIsRequired
= TRUE
;
2202 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED
, NULL
, NULL
, NULL
);
2206 // Exit current formset before do the reconnect.
2209 SettingLevel
= FormSetLevel
;
2212 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2213 SubmitForm (FormSet
, Form
, SettingLevel
);
2216 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2217 DiscardForm (FormSet
, Form
, SettingLevel
);
2221 FindNextMenu (Selection
, SettingLevel
);
2228 Call the retrieve type call back function for one question to get the initialize data.
2230 This function only used when in the initialize stage, because in this stage, the
2231 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2233 @param ConfigAccess The config access protocol produced by the hii driver.
2234 @param Statement The Question which need to call.
2235 @param FormSet The formset this question belong to.
2237 @retval EFI_SUCCESS The call back function executes successfully.
2238 @return Other value if the call back function failed to execute.
2241 ProcessRetrieveForQuestion (
2242 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2243 IN FORM_BROWSER_STATEMENT
*Statement
,
2244 IN FORM_BROWSER_FORMSET
*FormSet
2248 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2249 EFI_HII_VALUE
*HiiValue
;
2250 EFI_IFR_TYPE_VALUE
*TypeValue
;
2253 Status
= EFI_SUCCESS
;
2254 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2256 if (((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) || ConfigAccess
== NULL
) {
2257 return EFI_UNSUPPORTED
;
2260 HiiValue
= &Statement
->HiiValue
;
2261 TypeValue
= &HiiValue
->Value
;
2262 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2264 // For OrderedList, passing in the value buffer to Callback()
2266 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2269 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2270 Status
= ConfigAccess
->Callback (
2272 EFI_BROWSER_ACTION_RETRIEVE
,
2273 Statement
->QuestionId
,
2278 if (!EFI_ERROR (Status
) && HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2279 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2280 ASSERT (NewString
!= NULL
);
2282 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2283 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2284 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2285 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2287 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2289 FreePool (NewString
);
2296 The worker function that send the displays to the screen. On output,
2297 the selection made by user is returned.
2299 @param Selection On input, Selection tell setup browser the information
2300 about the Selection, form and formset to be displayed.
2301 On output, Selection return the screen item that is selected
2304 @retval EFI_SUCCESS The page is displayed successfully.
2305 @return Other value if the page failed to be diplayed.
2310 IN OUT UI_MENU_SELECTION
*Selection
2315 EFI_HANDLE NotifyHandle
;
2316 FORM_BROWSER_STATEMENT
*Statement
;
2317 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2319 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2322 // Register notify for Form package update
2324 Status
= mHiiDatabase
->RegisterPackageNotify (
2326 EFI_HII_PACKAGE_FORMS
,
2329 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2332 if (EFI_ERROR (Status
)) {
2337 // Initialize current settings of Questions in this FormSet
2339 InitializeCurrentSetting (Selection
->FormSet
);
2342 // Initilize Action field.
2344 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2347 // Clean the mCurFakeQestId value is formset refreshed.
2354 // Reset Status to prevent the next break from returning incorrect error status.
2356 Status
= EFI_SUCCESS
;
2359 // IFR is updated, force to reparse the IFR binary
2360 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and
2361 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.
2363 if (mHiiPackageListUpdated
) {
2364 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2365 mHiiPackageListUpdated
= FALSE
;
2370 // Initialize Selection->Form
2372 if (Selection
->FormId
== 0) {
2374 // Zero FormId indicates display the first Form in a FormSet
2376 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2378 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2379 Selection
->FormId
= Selection
->Form
->FormId
;
2381 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2384 if (Selection
->Form
== NULL
) {
2386 // No Form to display
2388 Status
= EFI_NOT_FOUND
;
2393 // Check Form is suppressed.
2395 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2396 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2398 // Form is suppressed.
2400 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
2401 Status
= EFI_NOT_FOUND
;
2407 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2408 // for each question with callback flag.
2409 // New form may be the first form, or the different form after another form close.
2411 if (((Selection
->Handle
!= mCurrentHiiHandle
) ||
2412 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2413 (Selection
->FormId
!= mCurrentFormId
))) {
2415 // Update Retrieve flag.
2417 mFinishRetrieveCall
= FALSE
;
2420 // Keep current form information
2422 mCurrentHiiHandle
= Selection
->Handle
;
2423 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2424 mCurrentFormId
= Selection
->FormId
;
2426 if (ConfigAccess
!= NULL
) {
2427 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2428 if (EFI_ERROR (Status
)) {
2433 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2435 if (mHiiPackageListUpdated
) {
2436 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2437 mHiiPackageListUpdated
= FALSE
;
2444 // Load Questions' Value for display
2446 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2447 if (EFI_ERROR (Status
)) {
2451 if (!mFinishRetrieveCall
) {
2453 // Finish call RETRIEVE callback for this form.
2455 mFinishRetrieveCall
= TRUE
;
2457 if (ConfigAccess
!= NULL
) {
2458 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2459 if (EFI_ERROR (Status
)) {
2464 // IFR is updated during callback of open form, force to reparse the IFR binary
2466 if (mHiiPackageListUpdated
) {
2467 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2468 mHiiPackageListUpdated
= FALSE
;
2477 Status
= DisplayForm ();
2478 if (EFI_ERROR (Status
)) {
2483 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2485 Statement
= Selection
->Statement
;
2486 if (Statement
!= NULL
) {
2487 if ((ConfigAccess
!= NULL
) &&
2488 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2489 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2490 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2491 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2493 // Process dynamic update ref opcode.
2495 if (!EFI_ERROR (Status
)) {
2496 Status
= ProcessGotoOpCode(Statement
, Selection
);
2500 // Callback return error status or status return from process goto opcode.
2502 if (EFI_ERROR (Status
)) {
2504 // Cross reference will not be taken, restore all essential field
2506 Selection
->Handle
= mCurrentHiiHandle
;
2507 CopyMem (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
, sizeof (EFI_GUID
));
2508 Selection
->FormId
= mCurrentFormId
;
2509 Selection
->QuestionId
= 0;
2510 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2515 if (!EFI_ERROR (Status
) &&
2516 (Statement
->Operand
!= EFI_IFR_REF_OP
) &&
2517 ((Statement
->Storage
== NULL
) || (Statement
->Storage
!= NULL
&& Statement
->ValueChanged
))) {
2519 // Only question value has been changed, browser will trig CHANGED callback.
2521 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2523 //check whether the question value changed compared with buffer value
2524 //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen
2526 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2530 // Do the question validation.
2532 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2533 if (!EFI_ERROR (Status
) && (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2534 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2536 // Verify whether question value has checked, update the ValueChanged flag in Question.
2538 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2543 // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage
2544 // and process question success till here, trig the gResetFlag/gFlagReconnect.
2546 if ((Status
== EFI_SUCCESS
) &&
2547 (Statement
->Storage
== NULL
)) {
2548 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2549 gResetRequiredFormLevel
= TRUE
;
2550 gResetRequiredSystemLevel
= 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 (