2 Utility functions for UI presentation.
4 Copyright (c) 2004 - 2014, 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 UINT32 gBrowserStatus
= BROWSER_SUCCESS
;
26 UINT16 mCurFakeQestId
;
27 FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
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 Add empty function for event process function.
76 @param Event The Event need to be process
77 @param Context The context of the event.
82 SetupBrowserEmptyFunction (
90 Base on the opcode buffer info to get the display statement.
92 @param OpCode The input opcode buffer for this statement.
94 @retval Statement The statement use this opcode buffer.
97 FORM_DISPLAY_ENGINE_STATEMENT
*
99 IN EFI_IFR_OP_HEADER
*OpCode
102 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
105 Link
= GetFirstNode (&gDisplayFormData
.StatementListHead
);
106 while (!IsNull (&gDisplayFormData
.StatementListHead
, Link
)) {
107 DisplayStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
109 if (DisplayStatement
->OpCode
== OpCode
) {
110 return DisplayStatement
;
112 Link
= GetNextNode (&gDisplayFormData
.StatementListHead
, Link
);
119 Free the refresh event list.
128 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
130 while (!IsListEmpty (&mRefreshEventList
)) {
131 Link
= GetFirstNode (&mRefreshEventList
);
132 EventNode
= FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link
);
133 RemoveEntryList (&EventNode
->Link
);
135 gBS
->CloseEvent (EventNode
->RefreshEvent
);
137 FreePool (EventNode
);
142 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
145 @param Statement The statement need to check.
150 IN OUT FORM_BROWSER_STATEMENT
*Statement
153 GetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
156 // Reset FormPackage update flag
158 mHiiPackageListUpdated
= FALSE
;
161 // Question value may be changed, need invoke its Callback()
163 ProcessCallBackFunction (gCurrentSelection
, gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
165 if (mHiiPackageListUpdated
) {
167 // Package list is updated, force to reparse IFR binary of target Formset
169 mHiiPackageListUpdated
= FALSE
;
170 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
175 Refresh the question which has refresh guid event attribute.
177 @param Event The event which has this function related.
178 @param Context The input context info related to this event or the status code return to the caller.
187 FORM_BROWSER_STATEMENT
*Statement
;
189 Statement
= (FORM_BROWSER_STATEMENT
*)Context
;
190 UpdateStatement(Statement
);
191 gBS
->SignalEvent (mValueChangedEvent
);
196 Create refresh hook event for statement which has refresh event or interval.
198 @param Statement The statement need to check.
203 IN FORM_BROWSER_STATEMENT
*Statement
207 EFI_EVENT RefreshEvent
;
208 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
211 // If question has refresh guid, create the notify function.
213 Status
= gBS
->CreateEventEx (
218 &Statement
->RefreshGuid
,
220 ASSERT_EFI_ERROR (Status
);
222 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
223 ASSERT (EventNode
!= NULL
);
224 EventNode
->RefreshEvent
= RefreshEvent
;
225 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
229 Perform value check for a question.
231 @param Question The question need to do check.
232 @param Type Condition type need to check.
233 @param ErrorInfo Return info about the error.
235 @retval The check result.
239 IN FORM_BROWSER_STATEMENT
*Question
,
241 OUT STATEMENT_ERROR_INFO
*ErrorInfo
246 FORM_EXPRESSION
*Expression
;
247 LIST_ENTRY
*ListHead
;
250 RetVal
= STATEMENT_VALID
;
254 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
255 ListHead
= &Question
->InconsistentListHead
;
258 case EFI_HII_EXPRESSION_WARNING_IF
:
259 ListHead
= &Question
->WarningListHead
;
267 ASSERT (ListHead
!= NULL
);
268 Link
= GetFirstNode (ListHead
);
269 while (!IsNull (ListHead
, Link
)) {
270 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
271 Link
= GetNextNode (ListHead
, Link
);
274 // Evaluate the expression
276 Status
= EvaluateExpression (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Expression
);
277 if (EFI_ERROR (Status
)) {
281 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
282 ErrorInfo
->StringId
= Expression
->Error
;
284 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
285 ErrorInfo
->TimeOut
= 0;
286 RetVal
= INCOSISTENT_IF_TRUE
;
289 case EFI_HII_EXPRESSION_WARNING_IF
:
290 ErrorInfo
->TimeOut
= Expression
->TimeOut
;
291 RetVal
= WARNING_IF_TRUE
;
306 Perform value check for a question.
308 @param Form Form where Statement is in.
309 @param Statement Value will check for it.
310 @param InputValue New value will be checked.
311 @param ErrorInfo Return the error info for this check.
313 @retval TRUE Input Value is valid.
314 @retval FALSE Input Value is invalid.
319 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
320 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
321 IN EFI_HII_VALUE
*InputValue
,
322 OUT STATEMENT_ERROR_INFO
*ErrorInfo
325 FORM_BROWSER_STATEMENT
*Question
;
326 EFI_HII_VALUE BackUpValue
;
331 RetVal
= STATEMENT_VALID
;
333 ASSERT (Form
!= NULL
&& Statement
!= NULL
&& InputValue
!= NULL
&& ErrorInfo
!= NULL
);
335 Question
= GetBrowserStatement(Statement
);
336 ASSERT (Question
!= NULL
);
339 // Back up the quesion value.
341 switch (Question
->Operand
) {
342 case EFI_IFR_ORDERED_LIST_OP
:
343 BackUpBuffer
= AllocateCopyPool (Question
->StorageWidth
, Question
->BufferValue
);
344 ASSERT (BackUpBuffer
!= NULL
);
345 CopyMem (Question
->BufferValue
, InputValue
->Buffer
, Question
->StorageWidth
);
349 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
350 CopyMem (&Question
->HiiValue
, InputValue
, sizeof (EFI_HII_VALUE
));
355 // Do the inconsistentif check.
357 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
358 RetVal
= ConditionCheck(Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
, ErrorInfo
);
362 // Do the warningif check.
364 if (RetVal
== STATEMENT_VALID
&& !IsListEmpty (&Question
->WarningListHead
)) {
365 RetVal
= ConditionCheck(Question
, EFI_HII_EXPRESSION_WARNING_IF
, ErrorInfo
);
369 // Restore the quesion value.
371 switch (Question
->Operand
) {
372 case EFI_IFR_ORDERED_LIST_OP
:
373 CopyMem (Question
->BufferValue
, BackUpBuffer
, Question
->StorageWidth
);
377 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
386 Initialize the Display statement structure data.
388 @param DisplayStatement Pointer to the display Statement data strucure.
389 @param Statement The statement need to check.
392 InitializeDisplayStatement (
393 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
394 IN FORM_BROWSER_STATEMENT
*Statement
398 QUESTION_OPTION
*Option
;
399 DISPLAY_QUESTION_OPTION
*DisplayOption
;
400 FORM_DISPLAY_ENGINE_STATEMENT
*ParentStatement
;
402 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
403 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
404 DisplayStatement
->OpCode
= Statement
->OpCode
;
405 InitializeListHead (&DisplayStatement
->NestStatementList
);
406 InitializeListHead (&DisplayStatement
->OptionListHead
);
408 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
409 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
411 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
412 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
416 // Initilize the option list in statement.
418 Link
= GetFirstNode (&Statement
->OptionListHead
);
419 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
420 Option
= QUESTION_OPTION_FROM_LINK (Link
);
421 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
422 if ((Option
->SuppressExpression
!= NULL
) &&
423 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
427 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
428 ASSERT (DisplayOption
!= NULL
);
430 DisplayOption
->ImageId
= Option
->ImageId
;
431 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
432 DisplayOption
->OptionOpCode
= Option
->OpCode
;
433 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
436 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
439 // Some special op code need an extra buffer to save the data.
440 // Such as string, password, orderedlist...
442 if (Statement
->BufferValue
!= NULL
) {
444 // Ordered list opcode may not initilized, get default value here.
446 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
447 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
450 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
451 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
454 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
457 // Get the highlight statement for current form.
459 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
460 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
461 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
465 // Create the refresh event process function.
467 if (!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) {
468 CreateRefreshEvent (Statement
);
472 // For RTC type of date/time, set default refresh interval to be 1 second.
474 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
475 Statement
->RefreshInterval
= 1;
479 // Create the refresh guid hook event.
480 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
482 if ((!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) || (Statement
->RefreshInterval
!= 0)) {
483 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
487 // Save the password check function for later use.
489 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
490 DisplayStatement
->PasswordCheck
= PasswordCheck
;
494 // Save the validate check question for later use.
496 if (!IsListEmpty (&Statement
->InconsistentListHead
) || !IsListEmpty (&Statement
->WarningListHead
)) {
497 DisplayStatement
->ValidateQuestion
= QuestionCheck
;
501 // If this statement is nest in the subtitle, insert to the host statement.
502 // else insert to the form it belongs to.
504 if (Statement
->ParentStatement
!= NULL
) {
505 ParentStatement
= GetDisplayStatement(Statement
->ParentStatement
->OpCode
);
506 ASSERT (ParentStatement
!= NULL
);
507 InsertTailList(&ParentStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
509 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
514 Process for the refresh interval statement.
516 @param Event The Event need to be process
517 @param Context The context of the event.
522 RefreshIntervalProcess (
527 FORM_BROWSER_STATEMENT
*Statement
;
530 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
531 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
532 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
533 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
535 if (Statement
->RefreshInterval
== 0) {
539 UpdateStatement(Statement
);
542 gBS
->SignalEvent (mValueChangedEvent
);
547 Make a copy of the global hotkey info.
555 BROWSER_HOT_KEY
*HotKey
;
556 BROWSER_HOT_KEY
*CopyKey
;
559 Link
= GetFirstNode (&gBrowserHotKeyList
);
560 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
561 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
563 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
564 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
565 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
567 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
569 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
575 Get the extra question attribute from override question list.
577 @param QuestionId The question id for this request question.
579 @retval The attribute for this question or NULL if not found this
580 question in the list.
584 ProcessQuestionExtraAttr (
585 IN EFI_QUESTION_ID QuestionId
589 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
592 // Return HII_DISPLAY_NONE if input a invalid question id.
594 if (QuestionId
== 0) {
595 return HII_DISPLAY_NONE
;
598 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
599 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
600 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
601 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
603 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
604 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
605 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
606 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
607 return QuestionDesc
->Attribute
;
611 return HII_DISPLAY_NONE
;
616 Enum all statement in current form, find all the statement can be display and
617 add to the display form.
621 AddStatementToDisplayForm (
627 FORM_BROWSER_STATEMENT
*Statement
;
628 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
629 UINT8 MinRefreshInterval
;
630 EFI_EVENT RefreshIntervalEvent
;
631 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
632 BOOLEAN FormEditable
;
633 UINT32 ExtraAttribute
;
635 MinRefreshInterval
= 0;
636 FormEditable
= FALSE
;
639 // Process the statement outside the form, these statements are not recognized
642 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
643 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
644 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
645 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
647 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
648 ASSERT (DisplayStatement
!= NULL
);
649 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
650 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
651 DisplayStatement
->OpCode
= Statement
->OpCode
;
653 InitializeListHead (&DisplayStatement
->NestStatementList
);
654 InitializeListHead (&DisplayStatement
->OptionListHead
);
656 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
660 // Process the statement in this form.
662 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
663 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
664 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
665 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
668 // This statement can't be show, skip it.
670 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
675 // Check the extra attribute.
677 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
678 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
682 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
683 ASSERT (DisplayStatement
!= NULL
);
686 // Initialize this statement and add it to the display form.
688 InitializeDisplayStatement(DisplayStatement
, Statement
);
691 // Set the extra attribute.
693 DisplayStatement
->Attribute
|= ExtraAttribute
;
695 if (Statement
->Storage
!= NULL
) {
700 // Get the minimal refresh interval value for later use.
702 if ((Statement
->RefreshInterval
!= 0) &&
703 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
704 MinRefreshInterval
= Statement
->RefreshInterval
;
709 // Create the periodic timer for refresh interval statement.
711 if (MinRefreshInterval
!= 0) {
712 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
713 ASSERT_EFI_ERROR (Status
);
714 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
715 ASSERT_EFI_ERROR (Status
);
717 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
718 ASSERT (EventNode
!= NULL
);
719 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
720 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
724 // Update hotkey list field.
726 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
733 Initialize the SettingChangedFlag variable in the display form.
737 UpdateDataChangedFlag (
742 FORM_BROWSER_FORMSET
*LocalFormSet
;
744 gDisplayFormData
.SettingChangedFlag
= FALSE
;
746 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
747 gDisplayFormData
.SettingChangedFlag
= TRUE
;
752 // Base on the system level to check whether need to show the NV flag.
754 switch (gBrowserSettingScope
) {
757 // Check the maintain list to see whether there is any change.
759 Link
= GetFirstNode (&gBrowserFormSetList
);
760 while (!IsNull (&gBrowserFormSetList
, Link
)) {
761 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
762 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
763 gDisplayFormData
.SettingChangedFlag
= TRUE
;
766 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
771 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
772 gDisplayFormData
.SettingChangedFlag
= TRUE
;
784 Initialize the Display form structure data.
788 InitializeDisplayFormData (
794 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
795 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
796 gDisplayFormData
.ImageId
= 0;
797 gDisplayFormData
.AnimationId
= 0;
799 InitializeListHead (&gDisplayFormData
.StatementListHead
);
800 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
801 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
803 Status
= gBS
->CreateEvent (
806 SetupBrowserEmptyFunction
,
810 ASSERT_EFI_ERROR (Status
);
815 Free the kotkey info saved in form data.
823 BROWSER_HOT_KEY
*HotKey
;
826 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
827 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
828 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
830 RemoveEntryList (&HotKey
->Link
);
832 FreePool (HotKey
->KeyData
);
833 FreePool (HotKey
->HelpString
);
840 Update the Display form structure data.
844 UpdateDisplayFormData (
848 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
849 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
850 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
851 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
853 gDisplayFormData
.Attribute
= 0;
854 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
855 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
857 gDisplayFormData
.FormRefreshEvent
= NULL
;
858 gDisplayFormData
.HighLightedStatement
= NULL
;
860 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
861 gDisplayFormData
.ErrorString
= gErrorInfo
;
863 gBrowserStatus
= BROWSER_SUCCESS
;
866 UpdateDataChangedFlag ();
868 AddStatementToDisplayForm ();
873 Free the Display Statement structure data.
875 @param StatementList Point to the statement list which need to be free.
880 LIST_ENTRY
*StatementList
884 LIST_ENTRY
*OptionLink
;
885 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
886 DISPLAY_QUESTION_OPTION
*Option
;
889 // Free Statements/Questions
891 while (!IsListEmpty (StatementList
)) {
892 Link
= GetFirstNode (StatementList
);
893 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
898 while (!IsListEmpty (&Statement
->OptionListHead
)) {
899 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
900 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
901 RemoveEntryList (&Option
->Link
);
906 // Free nest statement List
908 if (!IsListEmpty (&Statement
->NestStatementList
)) {
909 FreeStatementData(&Statement
->NestStatementList
);
912 RemoveEntryList (&Statement
->DisplayLink
);
913 FreePool (Statement
);
919 Free the Display form structure data.
923 FreeDisplayFormData (
927 FreeStatementData (&gDisplayFormData
.StatementListHead
);
928 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
937 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
939 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
941 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
944 FORM_BROWSER_STATEMENT
*
945 GetBrowserStatement (
946 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
949 FORM_BROWSER_STATEMENT
*Statement
;
952 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
953 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
954 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
956 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
960 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
967 Update the ValueChanged status for questions in this form.
969 @param FormSet FormSet data structure.
970 @param Form Form data structure.
974 UpdateStatementStatusForForm (
975 IN FORM_BROWSER_FORMSET
*FormSet
,
976 IN FORM_BROWSER_FORM
*Form
980 FORM_BROWSER_STATEMENT
*Question
;
982 Link
= GetFirstNode (&Form
->StatementListHead
);
983 while (!IsNull (&Form
->StatementListHead
, Link
)) {
984 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
985 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
987 IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
992 Update the ValueChanged status for questions in this formset.
994 @param FormSet FormSet data structure.
998 UpdateStatementStatusForFormSet (
999 IN FORM_BROWSER_FORMSET
*FormSet
1003 FORM_BROWSER_FORM
*Form
;
1005 Link
= GetFirstNode (&FormSet
->FormListHead
);
1006 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1007 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1008 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1010 UpdateStatementStatusForForm (FormSet
, Form
);
1015 Update the ValueChanged status for questions.
1017 @param FormSet FormSet data structure.
1018 @param Form Form data structure.
1019 @param SettingScope Setting Scope for Default action.
1023 UpdateStatementStatus (
1024 IN FORM_BROWSER_FORMSET
*FormSet
,
1025 IN FORM_BROWSER_FORM
*Form
,
1026 IN BROWSER_SETTING_SCOPE SettingScope
1030 FORM_BROWSER_FORMSET
*LocalFormSet
;
1032 switch (SettingScope
) {
1034 Link
= GetFirstNode (&gBrowserFormSetList
);
1035 while (!IsNull (&gBrowserFormSetList
, Link
)) {
1036 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
1037 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
1038 if (!ValidateFormSet(LocalFormSet
)) {
1042 UpdateStatementStatusForFormSet (LocalFormSet
);
1047 UpdateStatementStatusForFormSet (FormSet
);
1051 UpdateStatementStatusForForm (FormSet
, Form
);
1061 Process the action request in user input.
1063 @param Action The user input action request info.
1064 @param DefaultId The user input default Id info.
1066 @retval EFI_SUCESSS This function always return successfully for now.
1078 // This is caused by use press ESC, and it should not combine with other action type.
1080 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
1081 FindNextMenu (gCurrentSelection
, FormLevel
);
1086 // Below is normal hotkey trigged action, these action maybe combine with each other.
1088 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
1089 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1092 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
1093 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
1094 UpdateStatementStatus (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1097 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
1098 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1099 if (EFI_ERROR (Status
)) {
1100 gBrowserStatus
= BROWSER_SUBMIT_FAIL
;
1104 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1105 gResetRequired
= TRUE
;
1108 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1110 // Form Exit without saving, Similar to ESC Key.
1111 // FormSet Exit without saving, Exit SendForm.
1112 // System Exit without saving, CallExitHandler and Exit SendForm.
1114 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1115 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1116 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1117 } else if (gBrowserSettingScope
== SystemLevel
) {
1118 if (ExitHandlerFunction
!= NULL
) {
1119 ExitHandlerFunction ();
1121 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1129 Check whether the formset guid is in this Hii package list.
1131 @param HiiHandle The HiiHandle for this HII package list.
1132 @param FormSetGuid The formset guid for the request formset.
1134 @retval TRUE Find the formset guid.
1135 @retval FALSE Not found the formset guid.
1139 GetFormsetGuidFromHiiHandle (
1140 IN EFI_HII_HANDLE HiiHandle
,
1141 IN EFI_GUID
*FormSetGuid
1144 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1148 UINT32 PackageListLength
;
1149 EFI_HII_PACKAGE_HEADER PackageHeader
;
1156 HiiPackageList
= NULL
;
1159 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1160 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1161 HiiPackageList
= AllocatePool (BufferSize
);
1162 ASSERT (HiiPackageList
!= NULL
);
1164 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1166 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1171 // Get Form package from this HII package List
1173 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1175 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1177 while (Offset
< PackageListLength
) {
1178 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1179 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1180 Offset
+= PackageHeader
.Length
;
1182 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1184 // Search FormSet in this Form Package
1186 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1187 while (Offset2
< PackageHeader
.Length
) {
1188 OpCodeData
= Package
+ Offset2
;
1190 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1191 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1197 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1205 FreePool (HiiPackageList
);
1211 Find HII Handle in the HII database associated with given Device Path.
1213 If DevicePath is NULL, then ASSERT.
1215 @param DevicePath Device Path associated with the HII package list
1217 @param FormsetGuid The formset guid for this formset.
1219 @retval Handle HII package list Handle associated with the Device
1221 @retval NULL Hii Package list handle is not found.
1225 DevicePathToHiiHandle (
1226 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1227 IN EFI_GUID
*FormsetGuid
1231 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1234 EFI_HANDLE DriverHandle
;
1235 EFI_HII_HANDLE
*HiiHandles
;
1236 EFI_HII_HANDLE HiiHandle
;
1238 ASSERT (DevicePath
!= NULL
);
1240 TmpDevicePath
= DevicePath
;
1242 // Locate Device Path Protocol handle buffer
1244 Status
= gBS
->LocateDevicePath (
1245 &gEfiDevicePathProtocolGuid
,
1249 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1254 // Retrieve all HII Handles from HII database
1256 HiiHandles
= HiiGetHiiHandles (NULL
);
1257 if (HiiHandles
== NULL
) {
1262 // Search Hii Handle by Driver Handle
1265 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1266 Status
= mHiiDatabase
->GetPackageListHandle (
1271 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1272 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1273 HiiHandle
= HiiHandles
[Index
];
1277 if (HiiHandle
!= NULL
) {
1283 FreePool (HiiHandles
);
1288 Find HII Handle in the HII database associated with given form set guid.
1290 If FormSetGuid is NULL, then ASSERT.
1292 @param ComparingGuid FormSet Guid associated with the HII package list
1295 @retval Handle HII package list Handle associated with the Device
1297 @retval NULL Hii Package list handle is not found.
1301 FormSetGuidToHiiHandle (
1302 EFI_GUID
*ComparingGuid
1305 EFI_HII_HANDLE
*HiiHandles
;
1306 EFI_HII_HANDLE HiiHandle
;
1309 ASSERT (ComparingGuid
!= NULL
);
1313 // Get all the Hii handles
1315 HiiHandles
= HiiGetHiiHandles (NULL
);
1316 ASSERT (HiiHandles
!= NULL
);
1319 // Search for formset of each class type
1321 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1322 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1323 HiiHandle
= HiiHandles
[Index
];
1327 if (HiiHandle
!= NULL
) {
1332 FreePool (HiiHandles
);
1338 check how to process the changed data in current form or form set.
1340 @param Selection On input, Selection tell setup browser the information
1341 about the Selection, form and formset to be displayed.
1342 On output, Selection return the screen item that is selected
1345 @param Scope Data save or discard scope, form or formset.
1347 @retval TRUE Success process the changed data, will return to the parent form.
1348 @retval FALSE Reject to process the changed data, will stay at current form.
1351 ProcessChangedData (
1352 IN OUT UI_MENU_SELECTION
*Selection
,
1353 IN BROWSER_SETTING_SCOPE Scope
1359 switch (mFormDisplay
->ConfirmDataChange()) {
1360 case BROWSER_ACTION_DISCARD
:
1361 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1364 case BROWSER_ACTION_SUBMIT
:
1365 SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1368 case BROWSER_ACTION_NONE
:
1374 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1384 Find parent formset menu(the first menu which has different formset) for current menu.
1385 If not find, just return to the first menu.
1387 @param Selection The selection info.
1392 IN OUT UI_MENU_SELECTION
*Selection
1395 FORM_ENTRY_INFO
*CurrentMenu
;
1396 FORM_ENTRY_INFO
*ParentMenu
;
1398 CurrentMenu
= Selection
->CurrentMenu
;
1399 ParentMenu
= UiFindParentMenu(CurrentMenu
);
1402 // Find a menu which has different formset guid with current.
1404 while (ParentMenu
!= NULL
&& CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1405 CurrentMenu
= ParentMenu
;
1406 ParentMenu
= UiFindParentMenu(CurrentMenu
);
1409 if (ParentMenu
!= NULL
) {
1410 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1411 Selection
->Handle
= ParentMenu
->HiiHandle
;
1412 Selection
->FormId
= ParentMenu
->FormId
;
1413 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1415 Selection
->FormId
= CurrentMenu
->FormId
;
1416 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1419 Selection
->Statement
= NULL
;
1423 Process the goto op code, update the info in the selection structure.
1425 @param Statement The statement belong to goto op code.
1426 @param Selection The selection info.
1428 @retval EFI_SUCCESS The menu process successfully.
1429 @return Other value if the process failed.
1433 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1434 IN OUT UI_MENU_SELECTION
*Selection
1438 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1439 FORM_BROWSER_FORM
*RefForm
;
1441 EFI_HII_HANDLE HiiHandle
;
1443 Status
= EFI_SUCCESS
;
1448 // Prepare the device path check, get the device path info first.
1450 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1451 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1455 // Check whether the device path string is a valid string.
1457 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1458 if (Selection
->Form
->ModalForm
) {
1463 // Goto another Hii Package list
1465 if (mPathFromText
!= NULL
) {
1466 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1467 if (DevicePath
!= NULL
) {
1468 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1469 FreePool (DevicePath
);
1471 FreePool (StringPtr
);
1474 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1476 gBrowserStatus
= BROWSER_PROTOCOL_NOT_FOUND
;
1477 FreePool (StringPtr
);
1481 if (HiiHandle
!= Selection
->Handle
) {
1483 // Goto another Formset, check for uncommitted data
1485 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1486 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1487 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1493 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1494 Selection
->Handle
= HiiHandle
;
1495 if (Selection
->Handle
== NULL
) {
1497 // If target Hii Handle not found, exit current formset.
1499 FindParentFormSet(Selection
);
1503 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1504 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1505 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1506 } else if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &gZeroGuid
)) {
1507 if (Selection
->Form
->ModalForm
) {
1510 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1512 // Goto another Formset, check for uncommitted data
1514 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1515 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1516 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1522 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1523 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1524 if (Selection
->Handle
== NULL
) {
1526 // If target Hii Handle not found, exit current formset.
1528 FindParentFormSet(Selection
);
1532 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1533 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1534 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1535 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1537 // Goto another Form, check for uncommitted data
1539 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1540 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1541 if (!ProcessChangedData (Selection
, FormLevel
)) {
1547 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1548 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1549 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1551 // Form is suppressed.
1553 gBrowserStatus
= BROWSER_FORM_SUPPRESS
;
1558 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1559 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1560 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1561 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1569 Process Question Config.
1571 @param Selection The UI menu selection.
1572 @param Question The Question to be peocessed.
1574 @retval EFI_SUCCESS Question Config process success.
1575 @retval Other Question Config process fail.
1579 ProcessQuestionConfig (
1580 IN UI_MENU_SELECTION
*Selection
,
1581 IN FORM_BROWSER_STATEMENT
*Question
1588 if (Question
->QuestionConfig
== 0) {
1595 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1596 if (ConfigResp
== NULL
) {
1597 return EFI_NOT_FOUND
;
1601 // Send config to Configuration Driver
1603 Status
= mHiiConfigRouting
->RouteConfig (
1614 Process the user input data.
1616 @param UserInput The user input data.
1617 @param ChangeHighlight Whether need to change the highlight statement.
1619 @retval EFI_SUCESSS This function always return successfully for now.
1624 IN USER_INPUT
*UserInput
,
1625 IN BOOLEAN ChangeHighlight
1629 FORM_BROWSER_STATEMENT
*Statement
;
1631 Status
= EFI_SUCCESS
;
1634 // When Exit from FormDisplay function, one of the below two cases must be true.
1636 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1639 // Remove the last highligh question id, this id will update when show next form.
1641 gCurrentSelection
->QuestionId
= 0;
1644 // First process the Action field in USER_INPUT.
1646 if (UserInput
->Action
!= 0) {
1647 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1648 if (EFI_ERROR (Status
)) {
1653 // Clear the highlight info.
1655 gCurrentSelection
->Statement
= NULL
;
1657 if (UserInput
->SelectedStatement
!= NULL
) {
1658 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1659 ASSERT (Statement
!= NULL
);
1661 // Save the current highlight menu in the menu history data.
1662 // which will be used when later browse back to this form.
1664 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1666 // For statement like text, actio, it not has question id.
1667 // So use FakeQuestionId to save the question.
1669 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1670 mCurFakeQestId
= Statement
->FakeQuestionId
;
1676 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1677 ASSERT (Statement
!= NULL
);
1679 gCurrentSelection
->Statement
= Statement
;
1681 if (ChangeHighlight
) {
1683 // This question is the current user select one,record it and later
1684 // show it as the highlight question.
1686 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1688 // For statement like text, actio, it not has question id.
1689 // So use FakeQuestionId to save the question.
1691 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1692 mCurFakeQestId
= Statement
->FakeQuestionId
;
1698 switch (Statement
->Operand
) {
1699 case EFI_IFR_REF_OP
:
1700 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1703 case EFI_IFR_ACTION_OP
:
1705 // Process the Config string <ConfigResp>
1707 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1710 case EFI_IFR_RESET_BUTTON_OP
:
1712 // Reset Question to default value specified by DefaultId
1714 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
);
1715 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1719 switch (Statement
->Operand
) {
1720 case EFI_IFR_STRING_OP
:
1721 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1722 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1723 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1724 FreePool (UserInput
->InputValue
.Buffer
);
1727 case EFI_IFR_PASSWORD_OP
:
1728 if (UserInput
->InputValue
.Buffer
== NULL
) {
1730 // User not input new password, just return.
1735 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1736 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1737 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1738 FreePool (UserInput
->InputValue
.Buffer
);
1740 // Two password match, send it to Configuration Driver
1742 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1743 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1745 // Clean the value after saved it.
1747 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1748 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1750 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1754 case EFI_IFR_ORDERED_LIST_OP
:
1755 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1759 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1771 Display form and wait for user to select one menu option, then return it.
1773 @retval EFI_SUCESSS This function always return successfully for now.
1782 USER_INPUT UserInput
;
1783 FORM_ENTRY_INFO
*CurrentMenu
;
1784 BOOLEAN ChangeHighlight
;
1786 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1789 // Update the menu history data.
1791 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1792 if (CurrentMenu
== NULL
) {
1794 // Current menu not found, add it to the menu tree
1796 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1797 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1798 ASSERT (CurrentMenu
!= NULL
);
1800 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1803 // Find currrent highlight statement.
1805 if (gCurrentSelection
->QuestionId
== 0) {
1807 // Highlight not specified, fetch it from cached menu
1809 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1813 // Evaluate all the Expressions in this Form
1815 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1816 if (EFI_ERROR (Status
)) {
1820 UpdateDisplayFormData ();
1823 // Three possible status maybe return.
1825 // EFI_INVALID_PARAMETER: The input dimension info is not valid.
1826 // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid
1827 // and an valid value has return.
1828 // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.
1830 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1831 if (EFI_ERROR (Status
) && Status
!= EFI_NOT_FOUND
) {
1832 FreeDisplayFormData();
1837 // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.
1838 // in this case, browser need to change the highlight menu.
1839 // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist
1840 // opcode and new valid value has return, browser core need to adjust
1841 // value for this opcode and shows this form again.
1843 ChangeHighlight
= (Status
== EFI_SUCCESS
? TRUE
:FALSE
);
1845 Status
= ProcessUserInput (&UserInput
, ChangeHighlight
);
1847 FreeDisplayFormData();
1853 Functions which are registered to receive notification of
1854 database events have this prototype. The actual event is encoded
1855 in NotifyType. The following table describes how PackageType,
1856 PackageGuid, Handle, and Package are used for each of the
1859 @param PackageType Package type of the notification.
1861 @param PackageGuid If PackageType is
1862 EFI_HII_PACKAGE_TYPE_GUID, then this is
1863 the pointer to the GUID from the Guid
1864 field of EFI_HII_PACKAGE_GUID_HEADER.
1865 Otherwise, it must be NULL.
1867 @param Package Points to the package referred to by the
1868 notification Handle The handle of the package
1869 list which contains the specified package.
1871 @param Handle The HII handle.
1873 @param NotifyType The type of change concerning the
1875 EFI_HII_DATABASE_NOTIFY_TYPE.
1881 IN UINT8 PackageType
,
1882 IN CONST EFI_GUID
*PackageGuid
,
1883 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1884 IN EFI_HII_HANDLE Handle
,
1885 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1888 mHiiPackageListUpdated
= TRUE
;
1894 Update the NV flag info for this form set.
1896 @param FormSet FormSet data structure.
1900 IsNvUpdateRequiredForFormSet (
1901 IN FORM_BROWSER_FORMSET
*FormSet
1905 FORM_BROWSER_FORM
*Form
;
1909 // Not finished question initialization, return FALSE.
1911 if (!FormSet
->QuestionInited
) {
1917 Link
= GetFirstNode (&FormSet
->FormListHead
);
1918 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1919 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1921 RetVal
= IsNvUpdateRequiredForForm(Form
);
1926 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1933 Update the NvUpdateRequired flag for a form.
1935 @param Form Form data structure.
1939 IsNvUpdateRequiredForForm (
1940 IN FORM_BROWSER_FORM
*Form
1944 FORM_BROWSER_STATEMENT
*Statement
;
1946 Link
= GetFirstNode (&Form
->StatementListHead
);
1947 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1948 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1950 if (Statement
->ValueChanged
) {
1954 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1961 Check whether the storage data for current form set is changed.
1963 @param FormSet FormSet data structure.
1965 @retval TRUE Data is changed.
1966 @retval FALSE Data is not changed.
1969 IsStorageDataChangedForFormSet (
1970 IN FORM_BROWSER_FORMSET
*FormSet
1974 FORMSET_STORAGE
*Storage
;
1975 BROWSER_STORAGE
*BrowserStorage
;
1976 CHAR16
*ConfigRespNew
;
1977 CHAR16
*ConfigRespOld
;
1981 ConfigRespNew
= NULL
;
1982 ConfigRespOld
= NULL
;
1985 // Request current settings from Configuration Driver
1987 Link
= GetFirstNode (&FormSet
->StorageListHead
);
1988 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
1989 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
1990 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
1992 BrowserStorage
= Storage
->BrowserStorage
;
1994 if (BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1998 if (Storage
->ElementCount
== 0) {
2002 StorageToConfigResp (BrowserStorage
, &ConfigRespNew
, Storage
->ConfigRequest
, TRUE
);
2003 StorageToConfigResp (BrowserStorage
, &ConfigRespOld
, Storage
->ConfigRequest
, FALSE
);
2004 ASSERT (ConfigRespNew
!= NULL
&& ConfigRespOld
!= NULL
);
2006 if (StrCmp (ConfigRespNew
, ConfigRespOld
) != 0) {
2010 FreePool (ConfigRespNew
);
2011 ConfigRespNew
= NULL
;
2013 FreePool (ConfigRespOld
);
2014 ConfigRespOld
= NULL
;
2025 Find menu which will show next time.
2027 @param Selection On input, Selection tell setup browser the information
2028 about the Selection, form and formset to be displayed.
2029 On output, Selection return the screen item that is selected
2031 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
2032 else, we need to exit current formset.
2034 @retval TRUE Exit current form.
2035 @retval FALSE User press ESC and keep in current form.
2039 IN OUT UI_MENU_SELECTION
*Selection
,
2040 IN BROWSER_SETTING_SCOPE SettingLevel
2043 FORM_ENTRY_INFO
*CurrentMenu
;
2044 FORM_ENTRY_INFO
*ParentMenu
;
2045 BROWSER_SETTING_SCOPE Scope
;
2047 CurrentMenu
= Selection
->CurrentMenu
;
2049 Scope
= FormSetLevel
;
2051 if (CurrentMenu
!= NULL
&& (ParentMenu
= UiFindParentMenu(CurrentMenu
)) != NULL
) {
2053 // we have a parent, so go to the parent menu
2055 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
2056 if (SettingLevel
== FormSetLevel
) {
2058 // Find a menu which has different formset guid with current.
2060 while (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
2061 CurrentMenu
= ParentMenu
;
2062 if ((ParentMenu
= UiFindParentMenu(CurrentMenu
)) == NULL
) {
2067 if (ParentMenu
!= NULL
) {
2068 Scope
= FormSetLevel
;
2074 Scope
= FormSetLevel
;
2079 // Form Level Check whether the data is changed.
2081 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
2082 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
2083 if (!ProcessChangedData(Selection
, Scope
)) {
2088 if (ParentMenu
!= NULL
) {
2090 // ParentMenu is found. Then, go to it.
2092 if (Scope
== FormLevel
) {
2093 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2095 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2096 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
2097 Selection
->Handle
= ParentMenu
->HiiHandle
;
2100 Selection
->Statement
= NULL
;
2102 Selection
->FormId
= ParentMenu
->FormId
;
2103 Selection
->QuestionId
= ParentMenu
->QuestionId
;
2106 // Clear highlight record for this menu
2108 CurrentMenu
->QuestionId
= 0;
2113 // Current in root page, exit the SendForm
2115 Selection
->Action
= UI_ACTION_EXIT
;
2121 Call the call back function for the question and process the return action.
2123 @param Selection On input, Selection tell setup browser the information
2124 about the Selection, form and formset to be displayed.
2125 On output, Selection return the screen item that is selected
2127 @param FormSet The formset this question belong to.
2128 @param Form The form this question belong to.
2129 @param Question The Question which need to call.
2130 @param Action The action request.
2131 @param SkipSaveOrDiscard Whether skip save or discard action.
2133 @retval EFI_SUCCESS The call back function excutes successfully.
2134 @return Other value if the call back function failed to excute.
2137 ProcessCallBackFunction (
2138 IN OUT UI_MENU_SELECTION
*Selection
,
2139 IN FORM_BROWSER_FORMSET
*FormSet
,
2140 IN FORM_BROWSER_FORM
*Form
,
2141 IN FORM_BROWSER_STATEMENT
*Question
,
2142 IN EFI_BROWSER_ACTION Action
,
2143 IN BOOLEAN SkipSaveOrDiscard
2147 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2148 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2149 EFI_HII_VALUE
*HiiValue
;
2150 EFI_IFR_TYPE_VALUE
*TypeValue
;
2151 FORM_BROWSER_STATEMENT
*Statement
;
2152 BOOLEAN SubmitFormIsRequired
;
2153 BOOLEAN DiscardFormIsRequired
;
2156 BROWSER_SETTING_SCOPE SettingLevel
;
2157 EFI_IFR_TYPE_VALUE BackUpValue
;
2158 UINT8
*BackUpBuffer
;
2160 ConfigAccess
= FormSet
->ConfigAccess
;
2161 SubmitFormIsRequired
= FALSE
;
2162 SettingLevel
= FormSetLevel
;
2163 DiscardFormIsRequired
= FALSE
;
2165 Status
= EFI_SUCCESS
;
2166 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2167 BackUpBuffer
= NULL
;
2169 if (ConfigAccess
== NULL
) {
2173 Link
= GetFirstNode (&Form
->StatementListHead
);
2174 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2175 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2176 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2179 // if Question != NULL, only process the question. Else, process all question in this form.
2181 if ((Question
!= NULL
) && (Statement
!= Question
)) {
2185 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2190 // Check whether Statement is disabled.
2192 if (Statement
->Expression
!= NULL
) {
2193 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
2198 HiiValue
= &Statement
->HiiValue
;
2199 TypeValue
= &HiiValue
->Value
;
2200 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2202 // For OrderedList, passing in the value buffer to Callback()
2204 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2208 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2210 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2211 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2212 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
+ sizeof(CHAR16
), Statement
->BufferValue
);
2214 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2218 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2219 Status
= ConfigAccess
->Callback (
2222 Statement
->QuestionId
,
2227 if (!EFI_ERROR (Status
)) {
2229 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2231 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2232 switch (ActionRequest
) {
2233 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2234 DiscardFormIsRequired
= TRUE
;
2235 gResetRequired
= TRUE
;
2239 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2240 SubmitFormIsRequired
= TRUE
;
2244 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2245 DiscardFormIsRequired
= TRUE
;
2249 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2250 SubmitFormIsRequired
= TRUE
;
2251 SettingLevel
= FormLevel
;
2255 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2256 DiscardFormIsRequired
= TRUE
;
2257 SettingLevel
= FormLevel
;
2261 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2262 SubmitFormIsRequired
= TRUE
;
2263 SettingLevel
= FormLevel
;
2266 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2267 DiscardFormIsRequired
= TRUE
;
2268 SettingLevel
= FormLevel
;
2277 // According the spec, return value from call back of "changing" and
2278 // "retrieve" should update to the question's temp buffer.
2280 if (Action
== EFI_BROWSER_ACTION_CHANGING
|| Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2281 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2285 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2286 // then the browser will use the value passed to Callback() and ignore the
2287 // value returned by Callback().
2289 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2290 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2291 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
+ sizeof(CHAR16
));
2293 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2296 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2300 // According the spec, return fail from call back of "changing" and
2301 // "retrieve", should restore the question's value.
2303 if ((Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) ||
2304 Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2305 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2308 if (Status
== EFI_UNSUPPORTED
) {
2310 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2312 Status
= EFI_SUCCESS
;
2316 if (BackUpBuffer
!= NULL
) {
2317 FreePool (BackUpBuffer
);
2321 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2322 SubmitForm (FormSet
, Form
, SettingLevel
);
2325 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2326 DiscardForm (FormSet
, Form
, SettingLevel
);
2330 FindNextMenu (Selection
, SettingLevel
);
2337 Call the retrieve type call back function for one question to get the initialize data.
2339 This function only used when in the initialize stage, because in this stage, the
2340 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2342 @param ConfigAccess The config access protocol produced by the hii driver.
2343 @param Statement The Question which need to call.
2345 @retval EFI_SUCCESS The call back function excutes successfully.
2346 @return Other value if the call back function failed to excute.
2349 ProcessRetrieveForQuestion (
2350 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2351 IN FORM_BROWSER_STATEMENT
*Statement
2355 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2356 EFI_HII_VALUE
*HiiValue
;
2357 EFI_IFR_TYPE_VALUE
*TypeValue
;
2359 Status
= EFI_SUCCESS
;
2360 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2362 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2363 return EFI_UNSUPPORTED
;
2366 HiiValue
= &Statement
->HiiValue
;
2367 TypeValue
= &HiiValue
->Value
;
2368 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2370 // For OrderedList, passing in the value buffer to Callback()
2372 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2375 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2376 Status
= ConfigAccess
->Callback (
2378 EFI_BROWSER_ACTION_RETRIEVE
,
2379 Statement
->QuestionId
,
2388 The worker function that send the displays to the screen. On output,
2389 the selection made by user is returned.
2391 @param Selection On input, Selection tell setup browser the information
2392 about the Selection, form and formset to be displayed.
2393 On output, Selection return the screen item that is selected
2396 @retval EFI_SUCCESS The page is displayed successfully.
2397 @return Other value if the page failed to be diplayed.
2402 IN OUT UI_MENU_SELECTION
*Selection
2407 EFI_HANDLE NotifyHandle
;
2408 FORM_BROWSER_STATEMENT
*Statement
;
2409 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2411 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2414 // Register notify for Form package update
2416 Status
= mHiiDatabase
->RegisterPackageNotify (
2418 EFI_HII_PACKAGE_FORMS
,
2421 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2424 if (EFI_ERROR (Status
)) {
2428 if ((Selection
->Handle
!= mCurrentHiiHandle
) ||
2429 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
))) {
2430 gFinishRetrieveCall
= FALSE
;
2434 // Initialize current settings of Questions in this FormSet
2436 InitializeCurrentSetting (Selection
->FormSet
);
2439 // Initilize Action field.
2441 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2444 // Clean the mCurFakeQestId value is formset refreshed.
2450 // IFR is updated, force to reparse the IFR binary
2452 if (mHiiPackageListUpdated
) {
2453 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2454 mHiiPackageListUpdated
= FALSE
;
2459 // Initialize Selection->Form
2461 if (Selection
->FormId
== 0) {
2463 // Zero FormId indicates display the first Form in a FormSet
2465 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2467 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2468 Selection
->FormId
= Selection
->Form
->FormId
;
2470 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2473 if (Selection
->Form
== NULL
) {
2475 // No Form to display
2477 Status
= EFI_NOT_FOUND
;
2482 // Check Form is suppressed.
2484 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2485 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2487 // Form is suppressed.
2489 gBrowserStatus
= BROWSER_FORM_SUPPRESS
;
2490 Status
= EFI_NOT_FOUND
;
2496 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2497 // for each question with callback flag.
2498 // New form may be the first form, or the different form after another form close.
2500 if ((ConfigAccess
!= NULL
) &&
2501 ((Selection
->Handle
!= mCurrentHiiHandle
) ||
2502 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2503 (Selection
->FormId
!= mCurrentFormId
))) {
2505 // Keep current form information
2507 mCurrentHiiHandle
= Selection
->Handle
;
2508 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2509 mCurrentFormId
= Selection
->FormId
;
2511 Status
= ProcessCallBackFunction (Selection
, gCurrentSelection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2512 if (EFI_ERROR (Status
)) {
2517 // IFR is updated during callback of open form, force to reparse the IFR binary
2519 if (mHiiPackageListUpdated
) {
2520 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2521 mHiiPackageListUpdated
= FALSE
;
2527 // Load Questions' Value for display
2529 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2530 if (EFI_ERROR (Status
)) {
2535 // Finish call RETRIEVE callback for this formset.
2537 gFinishRetrieveCall
= TRUE
;
2540 // IFR is updated during callback of read value, force to reparse the IFR binary
2542 if (mHiiPackageListUpdated
) {
2543 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2544 mHiiPackageListUpdated
= FALSE
;
2551 Status
= DisplayForm ();
2552 if (EFI_ERROR (Status
)) {
2557 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2559 Statement
= Selection
->Statement
;
2560 if (Statement
!= NULL
) {
2561 if ((ConfigAccess
!= NULL
) &&
2562 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2563 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2564 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2565 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2567 // Process dynamic update ref opcode.
2569 if (!EFI_ERROR (Status
)) {
2570 Status
= ProcessGotoOpCode(Statement
, Selection
);
2574 // Callback return error status or status return from process goto opcode.
2576 if (EFI_ERROR (Status
)) {
2578 // Cross reference will not be taken
2580 Selection
->FormId
= Selection
->Form
->FormId
;
2581 Selection
->QuestionId
= 0;
2585 if (!EFI_ERROR (Status
) && Statement
->Operand
!= EFI_IFR_REF_OP
) {
2586 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2588 } else if (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
) {
2589 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2593 // Verify whether question value has checked, update the ValueChanged flag in Question.
2595 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2599 // Check whether Exit flag is TRUE.
2601 if (gExitRequired
) {
2602 switch (gBrowserSettingScope
) {
2604 Selection
->Action
= UI_ACTION_EXIT
;
2609 FindNextMenu (Selection
, gBrowserSettingScope
);
2616 gExitRequired
= FALSE
;
2620 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2621 // for each question with callback flag.
2623 if ((ConfigAccess
!= NULL
) &&
2624 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2625 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2626 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2627 (Selection
->FormId
!= mCurrentFormId
))) {
2629 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2630 if (EFI_ERROR (Status
)) {
2634 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2638 // Reset current form information to the initial setting when error happens or form exit.
2640 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2641 mCurrentHiiHandle
= NULL
;
2642 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2647 // Unregister notify for Form package update
2649 mHiiDatabase
->UnregisterPackageNotify (