2 Utility functions for UI presentation.
4 Copyright (c) 2004 - 2013, 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
, Statement
, EFI_BROWSER_ACTION_CHANGING
, 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.
390 @param HostDisplayStatement Pointer to the display Statement data strucure which is an host statement.
393 InitializeDisplayStatement (
394 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
395 IN FORM_BROWSER_STATEMENT
*Statement
,
396 IN FORM_DISPLAY_ENGINE_STATEMENT
*HostDisplayStatement
400 QUESTION_OPTION
*Option
;
401 DISPLAY_QUESTION_OPTION
*DisplayOption
;
403 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
404 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
405 DisplayStatement
->OpCode
= Statement
->OpCode
;
406 InitializeListHead (&DisplayStatement
->NestStatementList
);
407 InitializeListHead (&DisplayStatement
->OptionListHead
);
409 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
410 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
412 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
413 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
417 // Initilize the option list in statement.
419 Link
= GetFirstNode (&Statement
->OptionListHead
);
420 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
421 Option
= QUESTION_OPTION_FROM_LINK (Link
);
422 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
423 if ((Option
->SuppressExpression
!= NULL
) &&
424 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
428 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
429 ASSERT (DisplayOption
!= NULL
);
431 DisplayOption
->ImageId
= Option
->ImageId
;
432 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
433 DisplayOption
->OptionOpCode
= Option
->OpCode
;
434 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
437 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
440 // Some special op code need an extra buffer to save the data.
441 // Such as string, password, orderedlist...
443 if (Statement
->BufferValue
!= NULL
) {
445 // Ordered list opcode may not initilized, get default value here.
447 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
448 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
451 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
452 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
455 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
458 // Get the highlight statement for current form.
460 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
461 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
462 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
466 // Create the refresh event process function.
468 if (!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) {
469 CreateRefreshEvent (Statement
);
473 // For RTC type of date/time, set default refresh interval to be 1 second.
475 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
476 Statement
->RefreshInterval
= 1;
480 // Create the refresh guid hook event.
481 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
483 if ((!CompareGuid (&Statement
->RefreshGuid
, &gZeroGuid
)) || (Statement
->RefreshInterval
!= 0)) {
484 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
488 // Save the password check function for later use.
490 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
491 DisplayStatement
->PasswordCheck
= PasswordCheck
;
495 // Save the validate check question for later use.
497 if (!IsListEmpty (&Statement
->InconsistentListHead
) || !IsListEmpty (&Statement
->WarningListHead
)) {
498 DisplayStatement
->ValidateQuestion
= QuestionCheck
;
502 // If this statement is nest in the subtitle, insert to the host statement.
503 // else insert to the form it belongs to.
505 if (Statement
->InSubtitle
) {
506 InsertTailList(&HostDisplayStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
508 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
513 Process for the refresh interval statement.
515 @param Event The Event need to be process
516 @param Context The context of the event.
521 RefreshIntervalProcess (
526 FORM_BROWSER_STATEMENT
*Statement
;
529 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
530 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
531 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
532 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
534 if (Statement
->RefreshInterval
== 0) {
538 UpdateStatement(Statement
);
541 gBS
->SignalEvent (mValueChangedEvent
);
546 Make a copy of the global hotkey info.
554 BROWSER_HOT_KEY
*HotKey
;
555 BROWSER_HOT_KEY
*CopyKey
;
558 Link
= GetFirstNode (&gBrowserHotKeyList
);
559 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
560 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
562 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
563 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
564 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
566 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
568 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
574 Get the extra question attribute from override question list.
576 @param QuestionId The question id for this request question.
578 @retval The attribute for this question or NULL if not found this
579 question in the list.
583 ProcessQuestionExtraAttr (
584 IN EFI_QUESTION_ID QuestionId
588 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
591 // Return HII_DISPLAY_NONE if input a invalid question id.
593 if (QuestionId
== 0) {
594 return HII_DISPLAY_NONE
;
597 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
598 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
599 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
600 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
602 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
603 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
604 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
605 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
606 return QuestionDesc
->Attribute
;
610 return HII_DISPLAY_NONE
;
615 Enum all statement in current form, find all the statement can be display and
616 add to the display form.
620 AddStatementToDisplayForm (
626 FORM_BROWSER_STATEMENT
*Statement
;
627 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
628 FORM_DISPLAY_ENGINE_STATEMENT
*HostDisplayStatement
;
629 UINT8 MinRefreshInterval
;
630 EFI_EVENT RefreshIntervalEvent
;
631 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
632 BOOLEAN FormEditable
;
633 UINT32 ExtraAttribute
;
635 HostDisplayStatement
= NULL
;
636 MinRefreshInterval
= 0;
637 FormEditable
= FALSE
;
640 // Process the statement outside the form, these statements are not recognized
643 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
644 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
645 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
646 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
648 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
649 ASSERT (DisplayStatement
!= NULL
);
650 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
651 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
652 DisplayStatement
->OpCode
= Statement
->OpCode
;
654 InitializeListHead (&DisplayStatement
->NestStatementList
);
655 InitializeListHead (&DisplayStatement
->OptionListHead
);
657 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
661 // Process the statement in this form.
663 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
664 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
665 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
666 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
669 // This statement can't be show, skip it.
671 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
676 // Check the extra attribute.
678 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
679 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
683 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
684 ASSERT (DisplayStatement
!= NULL
);
687 // Initialize this statement and add it to the display form.
689 InitializeDisplayStatement(DisplayStatement
, Statement
, HostDisplayStatement
);
692 // Set the extra attribute.
694 DisplayStatement
->Attribute
|= ExtraAttribute
;
697 // Save the Host statement info.
698 // Host statement may has nest statement follow it.
700 if (!Statement
->InSubtitle
) {
701 HostDisplayStatement
= DisplayStatement
;
704 if (Statement
->Storage
!= NULL
) {
709 // Get the minimal refresh interval value for later use.
711 if ((Statement
->RefreshInterval
!= 0) &&
712 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
713 MinRefreshInterval
= Statement
->RefreshInterval
;
718 // Create the periodic timer for refresh interval statement.
720 if (MinRefreshInterval
!= 0) {
721 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
722 ASSERT_EFI_ERROR (Status
);
723 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
724 ASSERT_EFI_ERROR (Status
);
726 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
727 ASSERT (EventNode
!= NULL
);
728 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
729 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
733 // Update hotkey list field.
735 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
742 Initialize the SettingChangedFlag variable in the display form.
746 UpdateDataChangedFlag (
751 FORM_BROWSER_FORMSET
*LocalFormSet
;
753 gDisplayFormData
.SettingChangedFlag
= FALSE
;
755 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
756 gDisplayFormData
.SettingChangedFlag
= TRUE
;
761 // Base on the system level to check whether need to show the NV flag.
763 switch (gBrowserSettingScope
) {
766 // Check the maintain list to see whether there is any change.
768 Link
= GetFirstNode (&gBrowserFormSetList
);
769 while (!IsNull (&gBrowserFormSetList
, Link
)) {
770 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
771 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
772 gDisplayFormData
.SettingChangedFlag
= TRUE
;
775 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
780 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
781 gDisplayFormData
.SettingChangedFlag
= TRUE
;
793 Initialize the Display form structure data.
797 InitializeDisplayFormData (
803 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
804 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
805 gDisplayFormData
.ImageId
= 0;
806 gDisplayFormData
.AnimationId
= 0;
808 InitializeListHead (&gDisplayFormData
.StatementListHead
);
809 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
810 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
812 Status
= gBS
->CreateEvent (
815 SetupBrowserEmptyFunction
,
819 ASSERT_EFI_ERROR (Status
);
824 Free the kotkey info saved in form data.
832 BROWSER_HOT_KEY
*HotKey
;
835 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
836 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
837 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
839 RemoveEntryList (&HotKey
->Link
);
841 FreePool (HotKey
->KeyData
);
842 FreePool (HotKey
->HelpString
);
849 Update the Display form structure data.
853 UpdateDisplayFormData (
857 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
858 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
859 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
860 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
862 gDisplayFormData
.Attribute
= 0;
863 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
864 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
866 gDisplayFormData
.FormRefreshEvent
= NULL
;
867 gDisplayFormData
.HighLightedStatement
= NULL
;
869 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
870 gDisplayFormData
.ErrorString
= gErrorInfo
;
872 gBrowserStatus
= BROWSER_SUCCESS
;
875 UpdateDataChangedFlag ();
877 AddStatementToDisplayForm ();
882 Free the Display Statement structure data.
884 @param StatementList Point to the statement list which need to be free.
889 LIST_ENTRY
*StatementList
893 LIST_ENTRY
*OptionLink
;
894 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
895 DISPLAY_QUESTION_OPTION
*Option
;
898 // Free Statements/Questions
900 while (!IsListEmpty (StatementList
)) {
901 Link
= GetFirstNode (StatementList
);
902 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
907 while (!IsListEmpty (&Statement
->OptionListHead
)) {
908 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
909 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
910 RemoveEntryList (&Option
->Link
);
915 // Free nest statement List
917 if (!IsListEmpty (&Statement
->NestStatementList
)) {
918 FreeStatementData(&Statement
->NestStatementList
);
921 RemoveEntryList (&Statement
->DisplayLink
);
922 FreePool (Statement
);
928 Free the Display form structure data.
932 FreeDisplayFormData (
936 FreeStatementData (&gDisplayFormData
.StatementListHead
);
937 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
946 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
948 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
950 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
953 FORM_BROWSER_STATEMENT
*
954 GetBrowserStatement (
955 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
958 FORM_BROWSER_STATEMENT
*Statement
;
961 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
962 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
963 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
965 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
969 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
977 Process the action request in user input.
979 @param Action The user input action request info.
980 @param DefaultId The user input default Id info.
982 @retval EFI_SUCESSS This function always return successfully for now.
994 // This is caused by use press ESC, and it should not combine with other action type.
996 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
997 FindNextMenu (gCurrentSelection
, FormLevel
);
1002 // Below is normal hotkey trigged action, these action maybe combine with each other.
1004 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
1005 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1008 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
1009 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
1012 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
1013 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1014 if (EFI_ERROR (Status
)) {
1015 gBrowserStatus
= BROWSER_SUBMIT_FAIL
;
1019 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1020 gResetRequired
= TRUE
;
1023 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1025 // Form Exit without saving, Similar to ESC Key.
1026 // FormSet Exit without saving, Exit SendForm.
1027 // System Exit without saving, CallExitHandler and Exit SendForm.
1029 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1030 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1031 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1032 } else if (gBrowserSettingScope
== SystemLevel
) {
1033 if (ExitHandlerFunction
!= NULL
) {
1034 ExitHandlerFunction ();
1036 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1045 Find HII Handle in the HII database associated with given Device Path.
1047 If DevicePath is NULL, then ASSERT.
1049 @param DevicePath Device Path associated with the HII package list
1052 @retval Handle HII package list Handle associated with the Device
1054 @retval NULL Hii Package list handle is not found.
1059 DevicePathToHiiHandle (
1060 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1064 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1069 EFI_HANDLE DriverHandle
;
1070 EFI_HII_HANDLE
*HiiHandles
;
1071 EFI_HII_HANDLE HiiHandle
;
1073 ASSERT (DevicePath
!= NULL
);
1075 TmpDevicePath
= DevicePath
;
1077 // Locate Device Path Protocol handle buffer
1079 Status
= gBS
->LocateDevicePath (
1080 &gEfiDevicePathProtocolGuid
,
1084 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1089 // Retrieve all HII Handles from HII database
1091 BufferSize
= 0x1000;
1092 HiiHandles
= AllocatePool (BufferSize
);
1093 ASSERT (HiiHandles
!= NULL
);
1094 Status
= mHiiDatabase
->ListPackageLists (
1096 EFI_HII_PACKAGE_TYPE_ALL
,
1101 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1102 FreePool (HiiHandles
);
1103 HiiHandles
= AllocatePool (BufferSize
);
1104 ASSERT (HiiHandles
!= NULL
);
1106 Status
= mHiiDatabase
->ListPackageLists (
1108 EFI_HII_PACKAGE_TYPE_ALL
,
1115 if (EFI_ERROR (Status
)) {
1116 FreePool (HiiHandles
);
1121 // Search Hii Handle by Driver Handle
1124 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
1125 for (Index
= 0; Index
< HandleCount
; Index
++) {
1126 Status
= mHiiDatabase
->GetPackageListHandle (
1131 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1132 HiiHandle
= HiiHandles
[Index
];
1137 FreePool (HiiHandles
);
1142 Find HII Handle in the HII database associated with given form set guid.
1144 If FormSetGuid is NULL, then ASSERT.
1146 @param ComparingGuid FormSet Guid associated with the HII package list
1149 @retval Handle HII package list Handle associated with the Device
1151 @retval NULL Hii Package list handle is not found.
1155 FormSetGuidToHiiHandle (
1156 EFI_GUID
*ComparingGuid
1159 EFI_HII_HANDLE
*HiiHandles
;
1161 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1165 UINT32 PackageListLength
;
1166 EFI_HII_PACKAGE_HEADER PackageHeader
;
1170 EFI_HII_HANDLE HiiHandle
;
1172 ASSERT (ComparingGuid
!= NULL
);
1176 // Get all the Hii handles
1178 HiiHandles
= HiiGetHiiHandles (NULL
);
1179 ASSERT (HiiHandles
!= NULL
);
1182 // Search for formset of each class type
1184 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1186 HiiPackageList
= NULL
;
1187 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandles
[Index
], &BufferSize
, HiiPackageList
);
1188 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1189 HiiPackageList
= AllocatePool (BufferSize
);
1190 ASSERT (HiiPackageList
!= NULL
);
1192 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandles
[Index
], &BufferSize
, HiiPackageList
);
1194 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1199 // Get Form package from this HII package List
1201 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1203 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1205 while (Offset
< PackageListLength
) {
1206 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1207 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1209 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1211 // Search FormSet in this Form Package
1213 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1214 while (Offset2
< PackageHeader
.Length
) {
1215 OpCodeData
= Package
+ Offset2
;
1217 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1219 // Try to compare against formset GUID
1221 if (CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
1222 HiiHandle
= HiiHandles
[Index
];
1227 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1230 if (HiiHandle
!= NULL
) {
1233 Offset
+= PackageHeader
.Length
;
1236 FreePool (HiiPackageList
);
1237 if (HiiHandle
!= NULL
) {
1242 FreePool (HiiHandles
);
1248 check how to process the changed data in current form or form set.
1250 @param Selection On input, Selection tell setup browser the information
1251 about the Selection, form and formset to be displayed.
1252 On output, Selection return the screen item that is selected
1255 @param Scope Data save or discard scope, form or formset.
1257 @retval TRUE Success process the changed data, will return to the parent form.
1258 @retval FALSE Reject to process the changed data, will stay at current form.
1261 ProcessChangedData (
1262 IN OUT UI_MENU_SELECTION
*Selection
,
1263 IN BROWSER_SETTING_SCOPE Scope
1269 switch (mFormDisplay
->ConfirmDataChange()) {
1270 case BROWSER_ACTION_DISCARD
:
1271 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1274 case BROWSER_ACTION_SUBMIT
:
1275 SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1278 case BROWSER_ACTION_NONE
:
1284 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1294 Find parent formset menu(the first menu which has different formset) for current menu.
1295 If not find, just return to the first menu.
1297 @param Selection The selection info.
1302 IN OUT UI_MENU_SELECTION
*Selection
1305 FORM_ENTRY_INFO
*CurrentMenu
;
1306 FORM_ENTRY_INFO
*ParentMenu
;
1308 CurrentMenu
= Selection
->CurrentMenu
;
1309 ParentMenu
= UiFindParentMenu(CurrentMenu
);
1312 // Find a menu which has different formset guid with current.
1314 while (ParentMenu
!= NULL
&& CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1315 CurrentMenu
= ParentMenu
;
1316 ParentMenu
= UiFindParentMenu(CurrentMenu
);
1319 if (ParentMenu
!= NULL
) {
1320 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1321 Selection
->Handle
= ParentMenu
->HiiHandle
;
1322 Selection
->FormId
= ParentMenu
->FormId
;
1323 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1325 Selection
->FormId
= CurrentMenu
->FormId
;
1326 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1329 Selection
->Statement
= NULL
;
1333 Process the goto op code, update the info in the selection structure.
1335 @param Statement The statement belong to goto op code.
1336 @param Selection The selection info.
1338 @retval EFI_SUCCESS The menu process successfully.
1339 @return Other value if the process failed.
1343 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1344 IN OUT UI_MENU_SELECTION
*Selection
1348 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1349 FORM_BROWSER_FORM
*RefForm
;
1351 EFI_HII_HANDLE HiiHandle
;
1353 Status
= EFI_SUCCESS
;
1358 // Prepare the device path check, get the device path info first.
1360 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1361 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1365 // Check whether the device path string is a valid string.
1367 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
) {
1368 if (Selection
->Form
->ModalForm
) {
1373 // Goto another Hii Package list
1375 if (mPathFromText
!= NULL
) {
1376 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1377 if (DevicePath
!= NULL
) {
1378 HiiHandle
= DevicePathToHiiHandle (DevicePath
);
1379 FreePool (DevicePath
);
1381 FreePool (StringPtr
);
1384 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1386 gBrowserStatus
= BROWSER_PROTOCOL_NOT_FOUND
;
1387 FreePool (StringPtr
);
1391 if (HiiHandle
!= Selection
->Handle
) {
1393 // Goto another Formset, check for uncommitted data
1395 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1396 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1397 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1403 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1404 Selection
->Handle
= HiiHandle
;
1405 if (Selection
->Handle
== NULL
) {
1407 // If target Hii Handle not found, exit current formset.
1409 FindParentFormSet(Selection
);
1413 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1414 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1415 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1416 } else if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &gZeroGuid
)) {
1417 if (Selection
->Form
->ModalForm
) {
1420 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1422 // Goto another Formset, check for uncommitted data
1424 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1425 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1426 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1432 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1433 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1434 if (Selection
->Handle
== NULL
) {
1436 // If target Hii Handle not found, exit current formset.
1438 FindParentFormSet(Selection
);
1442 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1443 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1444 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1445 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1447 // Goto another Form, check for uncommitted data
1449 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1450 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1451 if (!ProcessChangedData (Selection
, FormLevel
)) {
1457 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1458 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1459 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1461 // Form is suppressed.
1463 gBrowserStatus
= BROWSER_FORM_SUPPRESS
;
1468 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1469 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1470 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1471 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1479 Process Question Config.
1481 @param Selection The UI menu selection.
1482 @param Question The Question to be peocessed.
1484 @retval EFI_SUCCESS Question Config process success.
1485 @retval Other Question Config process fail.
1489 ProcessQuestionConfig (
1490 IN UI_MENU_SELECTION
*Selection
,
1491 IN FORM_BROWSER_STATEMENT
*Question
1497 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1499 if (Question
->QuestionConfig
== 0) {
1506 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1507 if (ConfigResp
== NULL
) {
1508 return EFI_NOT_FOUND
;
1512 // Send config to Configuration Driver
1514 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
1515 if (ConfigAccess
== NULL
) {
1516 return EFI_UNSUPPORTED
;
1518 Status
= ConfigAccess
->RouteConfig (
1529 Process the user input data.
1531 @param UserInput The user input data.
1532 @param ChangeHighlight Whether need to change the highlight statement.
1534 @retval EFI_SUCESSS This function always return successfully for now.
1539 IN USER_INPUT
*UserInput
,
1540 IN BOOLEAN ChangeHighlight
1544 FORM_BROWSER_STATEMENT
*Statement
;
1546 Status
= EFI_SUCCESS
;
1549 // When Exit from FormDisplay function, one of the below two cases must be true.
1551 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1554 // Remove the last highligh question id, this id will update when show next form.
1556 gCurrentSelection
->QuestionId
= 0;
1559 // First process the Action field in USER_INPUT.
1561 if (UserInput
->Action
!= 0) {
1562 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1563 if (EFI_ERROR (Status
)) {
1568 // Clear the highlight info.
1570 gCurrentSelection
->Statement
= NULL
;
1572 if (UserInput
->SelectedStatement
!= NULL
) {
1573 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1574 ASSERT (Statement
!= NULL
);
1576 // Save the current highlight menu in the menu history data.
1577 // which will be used when later browse back to this form.
1579 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1581 // For statement like text, actio, it not has question id.
1582 // So use FakeQuestionId to save the question.
1584 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1585 mCurFakeQestId
= Statement
->FakeQuestionId
;
1591 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1592 ASSERT (Statement
!= NULL
);
1594 gCurrentSelection
->Statement
= Statement
;
1596 if (ChangeHighlight
) {
1598 // This question is the current user select one,record it and later
1599 // show it as the highlight question.
1601 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1603 // For statement like text, actio, it not has question id.
1604 // So use FakeQuestionId to save the question.
1606 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1607 mCurFakeQestId
= Statement
->FakeQuestionId
;
1613 switch (Statement
->Operand
) {
1614 case EFI_IFR_REF_OP
:
1615 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1618 case EFI_IFR_ACTION_OP
:
1620 // Process the Config string <ConfigResp>
1622 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1625 case EFI_IFR_RESET_BUTTON_OP
:
1627 // Reset Question to default value specified by DefaultId
1629 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
);
1633 switch (Statement
->Operand
) {
1634 case EFI_IFR_STRING_OP
:
1635 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1636 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1637 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1638 FreePool (UserInput
->InputValue
.Buffer
);
1641 case EFI_IFR_PASSWORD_OP
:
1642 if (UserInput
->InputValue
.Buffer
== NULL
) {
1644 // User not input new password, just return.
1649 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1650 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1651 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1652 FreePool (UserInput
->InputValue
.Buffer
);
1654 // Two password match, send it to Configuration Driver
1656 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1657 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1659 // Clean the value after saved it.
1661 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1662 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1664 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1668 case EFI_IFR_ORDERED_LIST_OP
:
1669 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1673 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1685 Display form and wait for user to select one menu option, then return it.
1687 @retval EFI_SUCESSS This function always return successfully for now.
1696 USER_INPUT UserInput
;
1697 FORM_ENTRY_INFO
*CurrentMenu
;
1698 BOOLEAN ChangeHighlight
;
1700 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1703 // Update the menu history data.
1705 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1706 if (CurrentMenu
== NULL
) {
1708 // Current menu not found, add it to the menu tree
1710 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1711 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1712 ASSERT (CurrentMenu
!= NULL
);
1714 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1717 // Find currrent highlight statement.
1719 if (gCurrentSelection
->QuestionId
== 0) {
1721 // Highlight not specified, fetch it from cached menu
1723 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1727 // Evaluate all the Expressions in this Form
1729 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1730 if (EFI_ERROR (Status
)) {
1734 UpdateDisplayFormData ();
1737 // Three possible status maybe return.
1739 // EFI_INVALID_PARAMETER: The input dimension info is not valid.
1740 // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid
1741 // and an valid value has return.
1742 // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.
1744 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1745 if (EFI_ERROR (Status
) && Status
!= EFI_NOT_FOUND
) {
1746 FreeDisplayFormData();
1751 // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.
1752 // in this case, browser need to change the highlight menu.
1753 // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist
1754 // opcode and new valid value has return, browser core need to adjust
1755 // value for this opcode and shows this form again.
1757 ChangeHighlight
= (Status
== EFI_SUCCESS
? TRUE
:FALSE
);
1759 Status
= ProcessUserInput (&UserInput
, ChangeHighlight
);
1761 FreeDisplayFormData();
1767 Functions which are registered to receive notification of
1768 database events have this prototype. The actual event is encoded
1769 in NotifyType. The following table describes how PackageType,
1770 PackageGuid, Handle, and Package are used for each of the
1773 @param PackageType Package type of the notification.
1775 @param PackageGuid If PackageType is
1776 EFI_HII_PACKAGE_TYPE_GUID, then this is
1777 the pointer to the GUID from the Guid
1778 field of EFI_HII_PACKAGE_GUID_HEADER.
1779 Otherwise, it must be NULL.
1781 @param Package Points to the package referred to by the
1782 notification Handle The handle of the package
1783 list which contains the specified package.
1785 @param Handle The HII handle.
1787 @param NotifyType The type of change concerning the
1789 EFI_HII_DATABASE_NOTIFY_TYPE.
1795 IN UINT8 PackageType
,
1796 IN CONST EFI_GUID
*PackageGuid
,
1797 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1798 IN EFI_HII_HANDLE Handle
,
1799 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1802 mHiiPackageListUpdated
= TRUE
;
1808 Update the NV flag info for this form set.
1810 @param FormSet FormSet data structure.
1814 IsNvUpdateRequiredForFormSet (
1815 IN FORM_BROWSER_FORMSET
*FormSet
1819 FORM_BROWSER_FORM
*Form
;
1823 // Not finished question initialization, return FALSE.
1825 if (!FormSet
->QuestionInited
) {
1831 Link
= GetFirstNode (&FormSet
->FormListHead
);
1832 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1833 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1835 RetVal
= IsNvUpdateRequiredForForm(Form
);
1840 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1847 Update the NvUpdateRequired flag for a form.
1849 @param Form Form data structure.
1853 IsNvUpdateRequiredForForm (
1854 IN FORM_BROWSER_FORM
*Form
1858 FORM_BROWSER_STATEMENT
*Statement
;
1860 Link
= GetFirstNode (&Form
->StatementListHead
);
1861 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1862 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1864 if (Statement
->ValueChanged
) {
1868 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1875 Check whether the storage data for current form set is changed.
1877 @param FormSet FormSet data structure.
1879 @retval TRUE Data is changed.
1880 @retval FALSE Data is not changed.
1883 IsStorageDataChangedForFormSet (
1884 IN FORM_BROWSER_FORMSET
*FormSet
1888 FORMSET_STORAGE
*Storage
;
1889 BROWSER_STORAGE
*BrowserStorage
;
1890 CHAR16
*ConfigRespNew
;
1891 CHAR16
*ConfigRespOld
;
1895 ConfigRespNew
= NULL
;
1896 ConfigRespOld
= NULL
;
1899 // Request current settings from Configuration Driver
1901 Link
= GetFirstNode (&FormSet
->StorageListHead
);
1902 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
1903 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
1904 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
1906 BrowserStorage
= Storage
->BrowserStorage
;
1908 if (BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1912 if (Storage
->ElementCount
== 0) {
1916 StorageToConfigResp (BrowserStorage
, &ConfigRespNew
, Storage
->ConfigRequest
, TRUE
);
1917 StorageToConfigResp (BrowserStorage
, &ConfigRespOld
, Storage
->ConfigRequest
, FALSE
);
1918 ASSERT (ConfigRespNew
!= NULL
&& ConfigRespOld
!= NULL
);
1920 if (StrCmp (ConfigRespNew
, ConfigRespOld
) != 0) {
1924 FreePool (ConfigRespNew
);
1925 ConfigRespNew
= NULL
;
1927 FreePool (ConfigRespOld
);
1928 ConfigRespOld
= NULL
;
1939 Find menu which will show next time.
1941 @param Selection On input, Selection tell setup browser the information
1942 about the Selection, form and formset to be displayed.
1943 On output, Selection return the screen item that is selected
1945 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1946 else, we need to exit current formset.
1948 @retval TRUE Exit current form.
1949 @retval FALSE User press ESC and keep in current form.
1953 IN OUT UI_MENU_SELECTION
*Selection
,
1954 IN BROWSER_SETTING_SCOPE SettingLevel
1957 FORM_ENTRY_INFO
*CurrentMenu
;
1958 FORM_ENTRY_INFO
*ParentMenu
;
1959 BROWSER_SETTING_SCOPE Scope
;
1961 CurrentMenu
= Selection
->CurrentMenu
;
1963 Scope
= FormSetLevel
;
1965 if (CurrentMenu
!= NULL
&& (ParentMenu
= UiFindParentMenu(CurrentMenu
)) != NULL
) {
1967 // we have a parent, so go to the parent menu
1969 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1970 if (SettingLevel
== FormSetLevel
) {
1972 // Find a menu which has different formset guid with current.
1974 while (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1975 CurrentMenu
= ParentMenu
;
1976 if ((ParentMenu
= UiFindParentMenu(CurrentMenu
)) == NULL
) {
1981 if (ParentMenu
!= NULL
) {
1982 Scope
= FormSetLevel
;
1988 Scope
= FormSetLevel
;
1993 // Form Level Check whether the data is changed.
1995 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1996 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1997 if (!ProcessChangedData(Selection
, Scope
)) {
2002 if (ParentMenu
!= NULL
) {
2004 // ParentMenu is found. Then, go to it.
2006 if (Scope
== FormLevel
) {
2007 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2009 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2010 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
2011 Selection
->Handle
= ParentMenu
->HiiHandle
;
2014 Selection
->Statement
= NULL
;
2016 Selection
->FormId
= ParentMenu
->FormId
;
2017 Selection
->QuestionId
= ParentMenu
->QuestionId
;
2020 // Clear highlight record for this menu
2022 CurrentMenu
->QuestionId
= 0;
2027 // Current in root page, exit the SendForm
2029 Selection
->Action
= UI_ACTION_EXIT
;
2035 Call the call back function for the question and process the return action.
2037 @param Selection On input, Selection tell setup browser the information
2038 about the Selection, form and formset to be displayed.
2039 On output, Selection return the screen item that is selected
2041 @param Question The Question which need to call.
2042 @param Action The action request.
2043 @param SkipSaveOrDiscard Whether skip save or discard action.
2045 @retval EFI_SUCCESS The call back function excutes successfully.
2046 @return Other value if the call back function failed to excute.
2049 ProcessCallBackFunction (
2050 IN OUT UI_MENU_SELECTION
*Selection
,
2051 IN FORM_BROWSER_STATEMENT
*Question
,
2052 IN EFI_BROWSER_ACTION Action
,
2053 IN BOOLEAN SkipSaveOrDiscard
2057 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2058 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2059 EFI_HII_VALUE
*HiiValue
;
2060 EFI_IFR_TYPE_VALUE
*TypeValue
;
2061 FORM_BROWSER_STATEMENT
*Statement
;
2062 BOOLEAN SubmitFormIsRequired
;
2063 BOOLEAN DiscardFormIsRequired
;
2066 BROWSER_SETTING_SCOPE SettingLevel
;
2067 EFI_IFR_TYPE_VALUE BackUpValue
;
2068 UINT8
*BackUpBuffer
;
2070 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2071 SubmitFormIsRequired
= FALSE
;
2072 SettingLevel
= FormSetLevel
;
2073 DiscardFormIsRequired
= FALSE
;
2075 Status
= EFI_SUCCESS
;
2076 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2077 BackUpBuffer
= NULL
;
2079 if (ConfigAccess
== NULL
) {
2083 Link
= GetFirstNode (&Selection
->Form
->StatementListHead
);
2084 while (!IsNull (&Selection
->Form
->StatementListHead
, Link
)) {
2085 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2086 Link
= GetNextNode (&Selection
->Form
->StatementListHead
, Link
);
2089 // if Question != NULL, only process the question. Else, process all question in this form.
2091 if ((Question
!= NULL
) && (Statement
!= Question
)) {
2095 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2100 // Check whether Statement is disabled.
2102 if (Statement
->Expression
!= NULL
) {
2103 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressDisable
) {
2108 HiiValue
= &Statement
->HiiValue
;
2109 TypeValue
= &HiiValue
->Value
;
2110 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2112 // For OrderedList, passing in the value buffer to Callback()
2114 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2118 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2120 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2121 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2122 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
+ sizeof(CHAR16
), Statement
->BufferValue
);
2124 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2128 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2129 Status
= ConfigAccess
->Callback (
2132 Statement
->QuestionId
,
2137 if (!EFI_ERROR (Status
)) {
2139 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2141 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2142 switch (ActionRequest
) {
2143 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2144 DiscardFormIsRequired
= TRUE
;
2145 gResetRequired
= TRUE
;
2149 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2150 SubmitFormIsRequired
= TRUE
;
2154 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2155 DiscardFormIsRequired
= TRUE
;
2159 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2160 SubmitFormIsRequired
= TRUE
;
2161 SettingLevel
= FormLevel
;
2165 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2166 DiscardFormIsRequired
= TRUE
;
2167 SettingLevel
= FormLevel
;
2171 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2172 SubmitFormIsRequired
= TRUE
;
2173 SettingLevel
= FormLevel
;
2176 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2177 DiscardFormIsRequired
= TRUE
;
2178 SettingLevel
= FormLevel
;
2187 // According the spec, return value from call back of "changing" and
2188 // "retrieve" should update to the question's temp buffer.
2190 if (Action
== EFI_BROWSER_ACTION_CHANGING
|| Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2191 SetQuestionValue(Selection
->FormSet
, Selection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2195 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2196 // then the browser will use the value passed to Callback() and ignore the
2197 // value returned by Callback().
2199 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2200 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2201 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
+ sizeof(CHAR16
));
2203 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2206 SetQuestionValue(Selection
->FormSet
, Selection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2210 // According the spec, return fail from call back of "changing" and
2211 // "retrieve", should restore the question's value.
2213 if ((Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) ||
2214 Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2215 GetQuestionValue(Selection
->FormSet
, Selection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2218 if (Status
== EFI_UNSUPPORTED
) {
2220 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2222 Status
= EFI_SUCCESS
;
2226 if (BackUpBuffer
!= NULL
) {
2227 FreePool (BackUpBuffer
);
2231 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2232 SubmitForm (Selection
->FormSet
, Selection
->Form
, SettingLevel
);
2235 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2236 DiscardForm (Selection
->FormSet
, Selection
->Form
, SettingLevel
);
2240 FindNextMenu (Selection
, SettingLevel
);
2247 Call the retrieve type call back function for one question to get the initialize data.
2249 This function only used when in the initialize stage, because in this stage, the
2250 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2252 @param ConfigAccess The config access protocol produced by the hii driver.
2253 @param Statement The Question which need to call.
2255 @retval EFI_SUCCESS The call back function excutes successfully.
2256 @return Other value if the call back function failed to excute.
2259 ProcessRetrieveForQuestion (
2260 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2261 IN FORM_BROWSER_STATEMENT
*Statement
2265 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2266 EFI_HII_VALUE
*HiiValue
;
2267 EFI_IFR_TYPE_VALUE
*TypeValue
;
2269 Status
= EFI_SUCCESS
;
2270 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2272 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2273 return EFI_UNSUPPORTED
;
2276 HiiValue
= &Statement
->HiiValue
;
2277 TypeValue
= &HiiValue
->Value
;
2278 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2280 // For OrderedList, passing in the value buffer to Callback()
2282 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2285 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2286 Status
= ConfigAccess
->Callback (
2288 EFI_BROWSER_ACTION_RETRIEVE
,
2289 Statement
->QuestionId
,
2298 The worker function that send the displays to the screen. On output,
2299 the selection made by user is returned.
2301 @param Selection On input, Selection tell setup browser the information
2302 about the Selection, form and formset to be displayed.
2303 On output, Selection return the screen item that is selected
2306 @retval EFI_SUCCESS The page is displayed successfully.
2307 @return Other value if the page failed to be diplayed.
2312 IN OUT UI_MENU_SELECTION
*Selection
2317 EFI_HANDLE NotifyHandle
;
2318 FORM_BROWSER_STATEMENT
*Statement
;
2319 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2321 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2324 // Register notify for Form package update
2326 Status
= mHiiDatabase
->RegisterPackageNotify (
2328 EFI_HII_PACKAGE_FORMS
,
2331 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2334 if (EFI_ERROR (Status
)) {
2339 // Initialize current settings of Questions in this FormSet
2341 InitializeCurrentSetting (Selection
->FormSet
);
2344 // Initilize Action field.
2346 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2349 // Clean the mCurFakeQestId value is formset refreshed.
2355 // IFR is updated, force to reparse the IFR binary
2357 if (mHiiPackageListUpdated
) {
2358 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2359 mHiiPackageListUpdated
= FALSE
;
2364 // Initialize Selection->Form
2366 if (Selection
->FormId
== 0) {
2368 // Zero FormId indicates display the first Form in a FormSet
2370 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2372 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2373 Selection
->FormId
= Selection
->Form
->FormId
;
2375 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2378 if (Selection
->Form
== NULL
) {
2380 // No Form to display
2382 Status
= EFI_NOT_FOUND
;
2387 // Check Form is suppressed.
2389 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2390 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2392 // Form is suppressed.
2394 gBrowserStatus
= BROWSER_FORM_SUPPRESS
;
2395 Status
= EFI_NOT_FOUND
;
2401 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2402 // for each question with callback flag.
2403 // New form may be the first form, or the different form after another form close.
2405 if ((ConfigAccess
!= NULL
) &&
2406 ((Selection
->Handle
!= mCurrentHiiHandle
) ||
2407 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2408 (Selection
->FormId
!= mCurrentFormId
))) {
2410 // Keep current form information
2412 mCurrentHiiHandle
= Selection
->Handle
;
2413 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2414 mCurrentFormId
= Selection
->FormId
;
2416 Status
= ProcessCallBackFunction (Selection
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2417 if (EFI_ERROR (Status
)) {
2422 // IFR is updated during callback of open form, force to reparse the IFR binary
2424 if (mHiiPackageListUpdated
) {
2425 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2426 mHiiPackageListUpdated
= FALSE
;
2432 // Load Questions' Value for display
2434 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2435 if (EFI_ERROR (Status
)) {
2440 // IFR is updated during callback of read value, force to reparse the IFR binary
2442 if (mHiiPackageListUpdated
) {
2443 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2444 mHiiPackageListUpdated
= FALSE
;
2451 Status
= DisplayForm ();
2452 if (EFI_ERROR (Status
)) {
2457 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2459 Statement
= Selection
->Statement
;
2460 if (Statement
!= NULL
) {
2461 if ((ConfigAccess
!= NULL
) &&
2462 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2463 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2464 Status
= ProcessCallBackFunction(Selection
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2465 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2467 // Process dynamic update ref opcode.
2469 if (!EFI_ERROR (Status
)) {
2470 Status
= ProcessGotoOpCode(Statement
, Selection
);
2474 // Callback return error status or status return from process goto opcode.
2476 if (EFI_ERROR (Status
)) {
2478 // Cross reference will not be taken
2480 Selection
->FormId
= Selection
->Form
->FormId
;
2481 Selection
->QuestionId
= 0;
2485 if (!EFI_ERROR (Status
) && Statement
->Operand
!= EFI_IFR_REF_OP
) {
2486 ProcessCallBackFunction(Selection
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2488 } else if (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
) {
2489 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2494 // Check whether Exit flag is TRUE.
2496 if (gExitRequired
) {
2497 switch (gBrowserSettingScope
) {
2499 Selection
->Action
= UI_ACTION_EXIT
;
2504 FindNextMenu (Selection
, gBrowserSettingScope
);
2511 gExitRequired
= FALSE
;
2515 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2516 // for each question with callback flag.
2518 if ((ConfigAccess
!= NULL
) &&
2519 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2520 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2521 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2522 (Selection
->FormId
!= mCurrentFormId
))) {
2524 Status
= ProcessCallBackFunction (Selection
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2525 if (EFI_ERROR (Status
)) {
2529 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2533 // Reset current form information to the initial setting when error happens or form exit.
2535 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2536 mCurrentHiiHandle
= NULL
;
2537 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2542 // Unregister notify for Form package update
2544 mHiiDatabase
->UnregisterPackageNotify (