2 Utility functions for UI presentation.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 BOOLEAN mHiiPackageListUpdated
;
13 UI_MENU_SELECTION
*gCurrentSelection
;
14 EFI_HII_HANDLE mCurrentHiiHandle
= NULL
;
15 EFI_GUID mCurrentFormSetGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
16 UINT16 mCurrentFormId
= 0;
17 EFI_EVENT mValueChangedEvent
= NULL
;
18 LIST_ENTRY mRefreshEventList
= INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList
);
19 UINT16 mCurFakeQestId
;
20 FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
21 BOOLEAN mFinishRetrieveCall
= FALSE
;
24 Check whether the ConfigAccess protocol is available.
26 @param FormSet FormSet of which the ConfigAcces protocol need to be checked.
28 @retval EFI_SUCCESS The function executed successfully.
33 IN FORM_BROWSER_FORMSET
*FormSet
38 Status
= gBS
->HandleProtocol (
39 FormSet
->DriverHandle
,
40 &gEfiHiiConfigAccessProtocolGuid
,
41 (VOID
**) &FormSet
->ConfigAccess
43 if (EFI_ERROR (Status
)) {
45 // Configuration Driver don't attach ConfigAccess protocol to its HII package
46 // list, then there will be no configuration action required.
47 // Or the ConfigAccess protocol has been uninstalled.
49 FormSet
->ConfigAccess
= NULL
;
56 Evaluate all expressions in a Form.
58 @param FormSet FormSet this Form belongs to.
61 @retval EFI_SUCCESS The expression evaluated successfuly
65 EvaluateFormExpressions (
66 IN FORM_BROWSER_FORMSET
*FormSet
,
67 IN FORM_BROWSER_FORM
*Form
72 FORM_EXPRESSION
*Expression
;
74 Link
= GetFirstNode (&Form
->ExpressionListHead
);
75 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
76 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
77 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
79 if (Expression
->Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
||
80 Expression
->Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
||
81 Expression
->Type
== EFI_HII_EXPRESSION_WARNING_IF
||
82 Expression
->Type
== EFI_HII_EXPRESSION_WRITE
||
83 (Expression
->Type
== EFI_HII_EXPRESSION_READ
&& Form
->FormType
!= STANDARD_MAP_FORM_TYPE
)) {
85 // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
90 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
91 if (EFI_ERROR (Status
)) {
100 Base on the opcode buffer info to get the display statement.
102 @param OpCode The input opcode buffer for this statement.
104 @retval Statement The statement use this opcode buffer.
107 FORM_DISPLAY_ENGINE_STATEMENT
*
108 GetDisplayStatement (
109 IN EFI_IFR_OP_HEADER
*OpCode
112 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
115 Link
= GetFirstNode (&gDisplayFormData
.StatementListHead
);
116 while (!IsNull (&gDisplayFormData
.StatementListHead
, Link
)) {
117 DisplayStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
119 if (DisplayStatement
->OpCode
== OpCode
) {
120 return DisplayStatement
;
122 Link
= GetNextNode (&gDisplayFormData
.StatementListHead
, Link
);
129 Free the refresh event list.
138 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
140 while (!IsListEmpty (&mRefreshEventList
)) {
141 Link
= GetFirstNode (&mRefreshEventList
);
142 EventNode
= FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link
);
143 RemoveEntryList (&EventNode
->Link
);
145 gBS
->CloseEvent (EventNode
->RefreshEvent
);
147 FreePool (EventNode
);
152 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
155 @param Statement The statement need to check.
160 IN OUT FORM_BROWSER_STATEMENT
*Statement
163 GetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
166 // Reset FormPackage update flag
168 mHiiPackageListUpdated
= FALSE
;
171 // Question value may be changed, need invoke its Callback()
173 ProcessCallBackFunction (gCurrentSelection
, gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
175 if (mHiiPackageListUpdated
) {
177 // Package list is updated, force to reparse IFR binary of target Formset
179 mHiiPackageListUpdated
= FALSE
;
180 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
185 Refresh the question which has refresh guid event attribute.
187 @param Event The event which has this function related.
188 @param Context The input context info related to this event or the status code return to the caller.
192 RefreshEventNotifyForStatement(
197 FORM_BROWSER_STATEMENT
*Statement
;
199 Statement
= (FORM_BROWSER_STATEMENT
*)Context
;
200 UpdateStatement(Statement
);
201 gBS
->SignalEvent (mValueChangedEvent
);
205 Refresh the questions within this form.
207 @param Event The event which has this function related.
208 @param Context The input context info related to this event or the status code return to the caller.
212 RefreshEventNotifyForForm(
217 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
219 gBS
->SignalEvent (mValueChangedEvent
);
223 Create refresh hook event for statement which has refresh event or interval.
225 @param Statement The statement need to check.
229 CreateRefreshEventForStatement (
230 IN FORM_BROWSER_STATEMENT
*Statement
234 EFI_EVENT RefreshEvent
;
235 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
238 // If question has refresh guid, create the notify function.
240 Status
= gBS
->CreateEventEx (
243 RefreshEventNotifyForStatement
,
245 &Statement
->RefreshGuid
,
247 ASSERT_EFI_ERROR (Status
);
249 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
250 ASSERT (EventNode
!= NULL
);
251 EventNode
->RefreshEvent
= RefreshEvent
;
252 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
256 Create refresh hook event for form which has refresh event or interval.
258 @param Form The form need to check.
262 CreateRefreshEventForForm (
263 IN FORM_BROWSER_FORM
*Form
267 EFI_EVENT RefreshEvent
;
268 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
271 // If question has refresh guid, create the notify function.
273 Status
= gBS
->CreateEventEx (
276 RefreshEventNotifyForForm
,
280 ASSERT_EFI_ERROR (Status
);
282 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
283 ASSERT (EventNode
!= NULL
);
284 EventNode
->RefreshEvent
= RefreshEvent
;
285 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
290 Initialize the Display statement structure data.
292 @param DisplayStatement Pointer to the display Statement data strucure.
293 @param Statement The statement need to check.
296 InitializeDisplayStatement (
297 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
298 IN FORM_BROWSER_STATEMENT
*Statement
302 QUESTION_OPTION
*Option
;
303 DISPLAY_QUESTION_OPTION
*DisplayOption
;
304 FORM_DISPLAY_ENGINE_STATEMENT
*ParentStatement
;
306 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
307 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
308 DisplayStatement
->OpCode
= Statement
->OpCode
;
309 InitializeListHead (&DisplayStatement
->NestStatementList
);
310 InitializeListHead (&DisplayStatement
->OptionListHead
);
312 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
313 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
315 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
316 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
320 // Initilize the option list in statement.
322 Link
= GetFirstNode (&Statement
->OptionListHead
);
323 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
324 Option
= QUESTION_OPTION_FROM_LINK (Link
);
325 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
326 if ((Option
->SuppressExpression
!= NULL
) &&
327 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
331 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
332 ASSERT (DisplayOption
!= NULL
);
334 DisplayOption
->ImageId
= Option
->ImageId
;
335 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
336 DisplayOption
->OptionOpCode
= Option
->OpCode
;
337 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
340 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
343 // Some special op code need an extra buffer to save the data.
344 // Such as string, password, orderedlist...
346 if (Statement
->BufferValue
!= NULL
) {
348 // Ordered list opcode may not initilized, get default value here.
350 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
351 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
354 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
355 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
358 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
361 // Get the highlight statement for current form.
363 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
364 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
365 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
369 // Create the refresh event process function.
371 if (!IsZeroGuid (&Statement
->RefreshGuid
)) {
372 CreateRefreshEventForStatement (Statement
);
376 // For RTC type of date/time, set default refresh interval to be 1 second.
378 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
379 Statement
->RefreshInterval
= 1;
383 // Create the refresh guid hook event.
384 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
386 if ((!IsZeroGuid (&Statement
->RefreshGuid
)) || (Statement
->RefreshInterval
!= 0)) {
387 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
391 // Save the password check function for later use.
393 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
394 DisplayStatement
->PasswordCheck
= PasswordCheck
;
398 // If this statement is nest in the subtitle, insert to the host statement.
399 // else insert to the form it belongs to.
401 if (Statement
->ParentStatement
!= NULL
) {
402 ParentStatement
= GetDisplayStatement(Statement
->ParentStatement
->OpCode
);
403 ASSERT (ParentStatement
!= NULL
);
404 InsertTailList(&ParentStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
406 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
411 Process for the refresh interval statement.
413 @param Event The Event need to be process
414 @param Context The context of the event.
419 RefreshIntervalProcess (
424 FORM_BROWSER_STATEMENT
*Statement
;
427 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
428 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
429 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
430 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
432 if (Statement
->RefreshInterval
== 0) {
436 UpdateStatement(Statement
);
439 gBS
->SignalEvent (mValueChangedEvent
);
444 Make a copy of the global hotkey info.
452 BROWSER_HOT_KEY
*HotKey
;
453 BROWSER_HOT_KEY
*CopyKey
;
456 Link
= GetFirstNode (&gBrowserHotKeyList
);
457 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
458 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
460 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
461 ASSERT (CopyKey
!= NULL
);
462 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
463 ASSERT (CopyKey
->KeyData
!= NULL
);
464 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
465 ASSERT (CopyKey
->HelpString
!= NULL
);
467 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
469 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
475 Get the extra question attribute from override question list.
477 @param QuestionId The question id for this request question.
479 @retval The attribute for this question or NULL if not found this
480 question in the list.
484 ProcessQuestionExtraAttr (
485 IN EFI_QUESTION_ID QuestionId
489 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
492 // Return HII_DISPLAY_NONE if input a invalid question id.
494 if (QuestionId
== 0) {
495 return HII_DISPLAY_NONE
;
498 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
499 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
500 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
501 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
503 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
504 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
505 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
506 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
507 return QuestionDesc
->Attribute
;
511 return HII_DISPLAY_NONE
;
516 Enum all statement in current form, find all the statement can be display and
517 add to the display form.
521 AddStatementToDisplayForm (
527 FORM_BROWSER_STATEMENT
*Statement
;
528 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
529 UINT8 MinRefreshInterval
;
530 EFI_EVENT RefreshIntervalEvent
;
531 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
532 BOOLEAN FormEditable
;
533 UINT32 ExtraAttribute
;
535 MinRefreshInterval
= 0;
536 FormEditable
= FALSE
;
539 // Process the statement outside the form, these statements are not recognized
542 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
543 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
544 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
545 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
547 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
548 ASSERT (DisplayStatement
!= NULL
);
549 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
550 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
551 DisplayStatement
->OpCode
= Statement
->OpCode
;
553 InitializeListHead (&DisplayStatement
->NestStatementList
);
554 InitializeListHead (&DisplayStatement
->OptionListHead
);
556 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
560 // treat formset as statement outside the form,get its opcode.
562 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
563 ASSERT (DisplayStatement
!= NULL
);
565 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
566 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
567 DisplayStatement
->OpCode
= gCurrentSelection
->FormSet
->OpCode
;
569 InitializeListHead (&DisplayStatement
->NestStatementList
);
570 InitializeListHead (&DisplayStatement
->OptionListHead
);
572 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
575 // Process the statement in this form.
577 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
578 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
579 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
580 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
583 // This statement can't be show, skip it.
585 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
590 // Check the extra attribute.
592 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
593 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
597 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
598 ASSERT (DisplayStatement
!= NULL
);
601 // Initialize this statement and add it to the display form.
603 InitializeDisplayStatement(DisplayStatement
, Statement
);
606 // Set the extra attribute.
608 DisplayStatement
->Attribute
|= ExtraAttribute
;
610 if (Statement
->Storage
!= NULL
) {
615 // Get the minimal refresh interval value for later use.
617 if ((Statement
->RefreshInterval
!= 0) &&
618 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
619 MinRefreshInterval
= Statement
->RefreshInterval
;
624 // Create the periodic timer for refresh interval statement.
626 if (MinRefreshInterval
!= 0) {
627 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
628 ASSERT_EFI_ERROR (Status
);
629 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
630 ASSERT_EFI_ERROR (Status
);
632 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
633 ASSERT (EventNode
!= NULL
);
634 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
635 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
639 // Create the refresh event process function for Form.
641 if (!IsZeroGuid (&gCurrentSelection
->Form
->RefreshGuid
)) {
642 CreateRefreshEventForForm (gCurrentSelection
->Form
);
643 if (gDisplayFormData
.FormRefreshEvent
== NULL
) {
644 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
649 // Update hotkey list field.
651 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
658 Initialize the SettingChangedFlag variable in the display form.
662 UpdateDataChangedFlag (
667 FORM_BROWSER_FORMSET
*LocalFormSet
;
669 gDisplayFormData
.SettingChangedFlag
= FALSE
;
671 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
672 gDisplayFormData
.SettingChangedFlag
= TRUE
;
677 // Base on the system level to check whether need to show the NV flag.
679 switch (gBrowserSettingScope
) {
682 // Check the maintain list to see whether there is any change.
684 Link
= GetFirstNode (&gBrowserFormSetList
);
685 while (!IsNull (&gBrowserFormSetList
, Link
)) {
686 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
687 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
688 gDisplayFormData
.SettingChangedFlag
= TRUE
;
691 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
696 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
697 gDisplayFormData
.SettingChangedFlag
= TRUE
;
709 Initialize the Display form structure data.
713 InitializeDisplayFormData (
719 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
720 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
721 gDisplayFormData
.ImageId
= 0;
722 gDisplayFormData
.AnimationId
= 0;
724 InitializeListHead (&gDisplayFormData
.StatementListHead
);
725 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
726 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
728 Status
= gBS
->CreateEvent (
731 EfiEventEmptyFunction
,
735 ASSERT_EFI_ERROR (Status
);
740 Free the kotkey info saved in form data.
748 BROWSER_HOT_KEY
*HotKey
;
751 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
752 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
753 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
755 RemoveEntryList (&HotKey
->Link
);
757 FreePool (HotKey
->KeyData
);
758 FreePool (HotKey
->HelpString
);
765 Update the Display form structure data.
769 UpdateDisplayFormData (
773 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
774 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
775 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
776 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
778 gDisplayFormData
.Attribute
= 0;
779 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
780 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
782 gDisplayFormData
.FormRefreshEvent
= NULL
;
783 gDisplayFormData
.HighLightedStatement
= NULL
;
785 UpdateDataChangedFlag ();
787 AddStatementToDisplayForm ();
792 Free the Display Statement structure data.
794 @param StatementList Point to the statement list which need to be free.
799 LIST_ENTRY
*StatementList
803 LIST_ENTRY
*OptionLink
;
804 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
805 DISPLAY_QUESTION_OPTION
*Option
;
808 // Free Statements/Questions
810 while (!IsListEmpty (StatementList
)) {
811 Link
= GetFirstNode (StatementList
);
812 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
817 while (!IsListEmpty (&Statement
->OptionListHead
)) {
818 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
819 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
820 RemoveEntryList (&Option
->Link
);
825 // Free nest statement List
827 if (!IsListEmpty (&Statement
->NestStatementList
)) {
828 FreeStatementData(&Statement
->NestStatementList
);
831 RemoveEntryList (&Statement
->DisplayLink
);
832 FreePool (Statement
);
838 Free the Display form structure data.
842 FreeDisplayFormData (
846 FreeStatementData (&gDisplayFormData
.StatementListHead
);
847 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
856 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
858 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
860 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
863 FORM_BROWSER_STATEMENT
*
864 GetBrowserStatement (
865 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
868 FORM_BROWSER_STATEMENT
*Statement
;
871 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
872 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
873 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
875 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
879 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
886 Update the ValueChanged status for questions in this form.
888 @param FormSet FormSet data structure.
889 @param Form Form data structure.
893 UpdateStatementStatusForForm (
894 IN FORM_BROWSER_FORMSET
*FormSet
,
895 IN FORM_BROWSER_FORM
*Form
899 FORM_BROWSER_STATEMENT
*Question
;
901 Link
= GetFirstNode (&Form
->StatementListHead
);
902 while (!IsNull (&Form
->StatementListHead
, Link
)) {
903 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
904 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
907 // For password opcode, not set the the value changed flag.
909 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
913 IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
918 Update the ValueChanged status for questions in this formset.
920 @param FormSet FormSet data structure.
924 UpdateStatementStatusForFormSet (
925 IN FORM_BROWSER_FORMSET
*FormSet
929 FORM_BROWSER_FORM
*Form
;
931 Link
= GetFirstNode (&FormSet
->FormListHead
);
932 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
933 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
934 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
936 UpdateStatementStatusForForm (FormSet
, Form
);
941 Update the ValueChanged status for questions.
943 @param FormSet FormSet data structure.
944 @param Form Form data structure.
945 @param SettingScope Setting Scope for Default action.
949 UpdateStatementStatus (
950 IN FORM_BROWSER_FORMSET
*FormSet
,
951 IN FORM_BROWSER_FORM
*Form
,
952 IN BROWSER_SETTING_SCOPE SettingScope
956 FORM_BROWSER_FORMSET
*LocalFormSet
;
958 switch (SettingScope
) {
960 Link
= GetFirstNode (&gBrowserFormSetList
);
961 while (!IsNull (&gBrowserFormSetList
, Link
)) {
962 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
963 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
964 if (!ValidateFormSet(LocalFormSet
)) {
968 UpdateStatementStatusForFormSet (LocalFormSet
);
973 UpdateStatementStatusForFormSet (FormSet
);
977 UpdateStatementStatusForForm (FormSet
, Form
);
987 Process the action request in user input.
989 @param Action The user input action request info.
990 @param DefaultId The user input default Id info.
992 @retval EFI_SUCESSS This function always return successfully for now.
1002 // This is caused by use press ESC, and it should not combine with other action type.
1004 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
1005 FindNextMenu (gCurrentSelection
, FormLevel
);
1010 // Below is normal hotkey trigged action, these action maybe combine with each other.
1012 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
1013 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1016 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
1017 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1018 UpdateStatementStatus (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1021 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
1022 SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1025 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1026 gResetRequiredFormLevel
= TRUE
;
1027 gResetRequiredSystemLevel
= TRUE
;
1030 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1032 // Form Exit without saving, Similar to ESC Key.
1033 // FormSet Exit without saving, Exit SendForm.
1034 // System Exit without saving, CallExitHandler and Exit SendForm.
1036 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1037 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1038 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1039 } else if (gBrowserSettingScope
== SystemLevel
) {
1040 if (ExitHandlerFunction
!= NULL
) {
1041 ExitHandlerFunction ();
1043 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1051 Check whether the formset guid is in this Hii package list.
1053 @param HiiHandle The HiiHandle for this HII package list.
1054 @param FormSetGuid The formset guid for the request formset.
1056 @retval TRUE Find the formset guid.
1057 @retval FALSE Not found the formset guid.
1061 GetFormsetGuidFromHiiHandle (
1062 IN EFI_HII_HANDLE HiiHandle
,
1063 IN EFI_GUID
*FormSetGuid
1066 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1070 UINT32 PackageListLength
;
1071 EFI_HII_PACKAGE_HEADER PackageHeader
;
1078 HiiPackageList
= NULL
;
1081 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1082 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1083 HiiPackageList
= AllocatePool (BufferSize
);
1084 ASSERT (HiiPackageList
!= NULL
);
1086 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1088 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1093 // Get Form package from this HII package List
1095 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1097 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1099 while (Offset
< PackageListLength
) {
1100 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1101 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1102 Offset
+= PackageHeader
.Length
;
1104 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1106 // Search FormSet in this Form Package
1108 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1109 while (Offset2
< PackageHeader
.Length
) {
1110 OpCodeData
= Package
+ Offset2
;
1112 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1113 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1119 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1127 FreePool (HiiPackageList
);
1133 Find HII Handle in the HII database associated with given Device Path.
1135 If DevicePath is NULL, then ASSERT.
1137 @param DevicePath Device Path associated with the HII package list
1139 @param FormsetGuid The formset guid for this formset.
1141 @retval Handle HII package list Handle associated with the Device
1143 @retval NULL Hii Package list handle is not found.
1147 DevicePathToHiiHandle (
1148 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1149 IN EFI_GUID
*FormsetGuid
1153 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1156 EFI_HANDLE DriverHandle
;
1157 EFI_HII_HANDLE
*HiiHandles
;
1158 EFI_HII_HANDLE HiiHandle
;
1160 ASSERT (DevicePath
!= NULL
);
1162 TmpDevicePath
= DevicePath
;
1164 // Locate Device Path Protocol handle buffer
1166 Status
= gBS
->LocateDevicePath (
1167 &gEfiDevicePathProtocolGuid
,
1171 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1176 // Retrieve all HII Handles from HII database
1178 HiiHandles
= HiiGetHiiHandles (NULL
);
1179 if (HiiHandles
== NULL
) {
1184 // Search Hii Handle by Driver Handle
1187 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1188 Status
= mHiiDatabase
->GetPackageListHandle (
1193 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1194 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1195 HiiHandle
= HiiHandles
[Index
];
1199 if (HiiHandle
!= NULL
) {
1205 FreePool (HiiHandles
);
1210 Find HII Handle in the HII database associated with given form set guid.
1212 If FormSetGuid is NULL, then ASSERT.
1214 @param ComparingGuid FormSet Guid associated with the HII package list
1217 @retval Handle HII package list Handle associated with the Device
1219 @retval NULL Hii Package list handle is not found.
1223 FormSetGuidToHiiHandle (
1224 EFI_GUID
*ComparingGuid
1227 EFI_HII_HANDLE
*HiiHandles
;
1228 EFI_HII_HANDLE HiiHandle
;
1231 ASSERT (ComparingGuid
!= NULL
);
1235 // Get all the Hii handles
1237 HiiHandles
= HiiGetHiiHandles (NULL
);
1238 ASSERT (HiiHandles
!= NULL
);
1241 // Search for formset of each class type
1243 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1244 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1245 HiiHandle
= HiiHandles
[Index
];
1249 if (HiiHandle
!= NULL
) {
1254 FreePool (HiiHandles
);
1260 check how to process the changed data in current form or form set.
1262 @param Selection On input, Selection tell setup browser the information
1263 about the Selection, form and formset to be displayed.
1264 On output, Selection return the screen item that is selected
1267 @param Scope Data save or discard scope, form or formset.
1269 @retval TRUE Success process the changed data, will return to the parent form.
1270 @retval FALSE Reject to process the changed data, will stay at current form.
1273 ProcessChangedData (
1274 IN OUT UI_MENU_SELECTION
*Selection
,
1275 IN BROWSER_SETTING_SCOPE Scope
1282 switch (mFormDisplay
->ConfirmDataChange()) {
1283 case BROWSER_ACTION_DISCARD
:
1284 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1287 case BROWSER_ACTION_SUBMIT
:
1288 Status
= SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1289 if (EFI_ERROR (Status
)) {
1294 case BROWSER_ACTION_NONE
:
1300 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1310 Find parent formset menu(the first menu which has different formset) for current menu.
1311 If not find, just return to the first menu.
1313 @param Selection The selection info.
1318 IN OUT UI_MENU_SELECTION
*Selection
1321 FORM_ENTRY_INFO
*CurrentMenu
;
1322 FORM_ENTRY_INFO
*ParentMenu
;
1324 CurrentMenu
= Selection
->CurrentMenu
;
1325 ParentMenu
= UiFindParentMenu(CurrentMenu
, FormSetLevel
);
1327 if (ParentMenu
!= NULL
) {
1328 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1329 Selection
->Handle
= ParentMenu
->HiiHandle
;
1330 Selection
->FormId
= ParentMenu
->FormId
;
1331 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1333 Selection
->FormId
= CurrentMenu
->FormId
;
1334 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1337 Selection
->Statement
= NULL
;
1341 Process the goto op code, update the info in the selection structure.
1343 @param Statement The statement belong to goto op code.
1344 @param Selection The selection info.
1346 @retval EFI_SUCCESS The menu process successfully.
1347 @return Other value if the process failed.
1351 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1352 IN OUT UI_MENU_SELECTION
*Selection
1356 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1357 FORM_BROWSER_FORM
*RefForm
;
1359 EFI_HII_HANDLE HiiHandle
;
1361 Status
= EFI_SUCCESS
;
1366 // Prepare the device path check, get the device path info first.
1368 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1369 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1373 // Check whether the device path string is a valid string.
1375 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1376 if (Selection
->Form
->ModalForm
) {
1381 // Goto another Hii Package list
1383 if (mPathFromText
!= NULL
) {
1384 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1385 if (DevicePath
!= NULL
) {
1386 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1387 FreePool (DevicePath
);
1389 FreePool (StringPtr
);
1392 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1394 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND
, NULL
, NULL
, NULL
);
1395 FreePool (StringPtr
);
1399 if (HiiHandle
!= Selection
->Handle
) {
1401 // Goto another Formset, check for uncommitted data
1403 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1404 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1405 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1411 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1412 Selection
->Handle
= HiiHandle
;
1413 if (Selection
->Handle
== NULL
) {
1415 // If target Hii Handle not found, exit current formset.
1417 FindParentFormSet(Selection
);
1421 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1422 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1423 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1424 } else if (!IsZeroGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
)) {
1425 if (Selection
->Form
->ModalForm
) {
1428 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1430 // Goto another Formset, check for uncommitted data
1432 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1433 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1434 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1440 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1441 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1442 if (Selection
->Handle
== NULL
) {
1444 // If target Hii Handle not found, exit current formset.
1446 FindParentFormSet(Selection
);
1450 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1451 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1452 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1453 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1455 // Goto another Form, check for uncommitted data
1457 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1458 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1459 if (!ProcessChangedData (Selection
, FormLevel
)) {
1465 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1466 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1467 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1469 // Form is suppressed.
1471 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
1476 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1477 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1478 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1479 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1487 Process Question Config.
1489 @param Selection The UI menu selection.
1490 @param Question The Question to be peocessed.
1492 @retval EFI_SUCCESS Question Config process success.
1493 @retval Other Question Config process fail.
1497 ProcessQuestionConfig (
1498 IN UI_MENU_SELECTION
*Selection
,
1499 IN FORM_BROWSER_STATEMENT
*Question
1506 if (Question
->QuestionConfig
== 0) {
1513 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1514 if (ConfigResp
== NULL
) {
1515 return EFI_NOT_FOUND
;
1516 } else if (ConfigResp
[0] == L
'\0') {
1521 // Send config to Configuration Driver
1523 Status
= mHiiConfigRouting
->RouteConfig (
1534 Process the user input data.
1536 @param UserInput The user input data.
1538 @retval EFI_SUCESSS This function always return successfully for now.
1543 IN USER_INPUT
*UserInput
1547 FORM_BROWSER_STATEMENT
*Statement
;
1549 Status
= EFI_SUCCESS
;
1553 // When Exit from FormDisplay function, one of the below two cases must be true.
1555 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1558 // Remove the last highligh question id, this id will update when show next form.
1560 gCurrentSelection
->QuestionId
= 0;
1561 if (UserInput
->SelectedStatement
!= NULL
){
1562 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1563 ASSERT (Statement
!= NULL
);
1566 // This question is the current user select one,record it and later
1567 // show it as the highlight question.
1569 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1571 // For statement like text, actio, it not has question id.
1572 // So use FakeQuestionId to save the question.
1574 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1575 mCurFakeQestId
= Statement
->FakeQuestionId
;
1582 // First process the Action field in USER_INPUT.
1584 if (UserInput
->Action
!= 0) {
1585 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1586 gCurrentSelection
->Statement
= NULL
;
1588 ASSERT (Statement
!= NULL
);
1589 gCurrentSelection
->Statement
= Statement
;
1590 switch (Statement
->Operand
) {
1591 case EFI_IFR_REF_OP
:
1592 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1595 case EFI_IFR_ACTION_OP
:
1597 // Process the Config string <ConfigResp>
1599 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1602 case EFI_IFR_RESET_BUTTON_OP
:
1604 // Reset Question to default value specified by DefaultId
1606 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1607 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1611 switch (Statement
->Operand
) {
1612 case EFI_IFR_STRING_OP
:
1613 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1614 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1615 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1616 FreePool (UserInput
->InputValue
.Buffer
);
1619 case EFI_IFR_PASSWORD_OP
:
1620 if (UserInput
->InputValue
.Buffer
== NULL
) {
1622 // User not input new password, just return.
1627 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1628 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1629 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1630 ZeroMem (UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1631 FreePool (UserInput
->InputValue
.Buffer
);
1633 // Two password match, send it to Configuration Driver
1635 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1636 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1638 // Clean the value after saved it.
1640 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1641 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1643 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1647 case EFI_IFR_ORDERED_LIST_OP
:
1648 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1652 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1664 Display form and wait for user to select one menu option, then return it.
1666 @retval EFI_SUCESSS This function always return successfully for now.
1675 USER_INPUT UserInput
;
1676 FORM_ENTRY_INFO
*CurrentMenu
;
1678 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1681 // Update the menu history data.
1683 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1684 if (CurrentMenu
== NULL
) {
1686 // Current menu not found, add it to the menu tree
1688 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1689 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1690 ASSERT (CurrentMenu
!= NULL
);
1694 // Back up the form view history data for this form.
1696 UiCopyMenuList(&gCurrentSelection
->Form
->FormViewListHead
, &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
1698 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1700 if (gCurrentSelection
->QuestionId
== 0) {
1702 // Highlight not specified, fetch it from cached menu
1704 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1707 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1708 if (EFI_ERROR (Status
)) {
1712 UpdateDisplayFormData ();
1714 ASSERT (gDisplayFormData
.BrowserStatus
== BROWSER_SUCCESS
);
1715 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1716 if (EFI_ERROR (Status
)) {
1717 FreeDisplayFormData();
1721 CheckConfigAccess(gCurrentSelection
->FormSet
);
1723 Status
= ProcessUserInput (&UserInput
);
1724 FreeDisplayFormData();
1729 Functions which are registered to receive notification of
1730 database events have this prototype. The actual event is encoded
1731 in NotifyType. The following table describes how PackageType,
1732 PackageGuid, Handle, and Package are used for each of the
1735 @param PackageType Package type of the notification.
1737 @param PackageGuid If PackageType is
1738 EFI_HII_PACKAGE_TYPE_GUID, then this is
1739 the pointer to the GUID from the Guid
1740 field of EFI_HII_PACKAGE_GUID_HEADER.
1741 Otherwise, it must be NULL.
1743 @param Package Points to the package referred to by the
1744 notification Handle The handle of the package
1745 list which contains the specified package.
1747 @param Handle The HII handle.
1749 @param NotifyType The type of change concerning the
1751 EFI_HII_DATABASE_NOTIFY_TYPE.
1757 IN UINT8 PackageType
,
1758 IN CONST EFI_GUID
*PackageGuid
,
1759 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1760 IN EFI_HII_HANDLE Handle
,
1761 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1764 mHiiPackageListUpdated
= TRUE
;
1770 Update the NV flag info for this form set.
1772 @param FormSet FormSet data structure.
1776 IsNvUpdateRequiredForFormSet (
1777 IN FORM_BROWSER_FORMSET
*FormSet
1781 FORM_BROWSER_FORM
*Form
;
1785 // Not finished question initialization, return FALSE.
1787 if (!FormSet
->QuestionInited
) {
1793 Link
= GetFirstNode (&FormSet
->FormListHead
);
1794 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1795 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1797 RetVal
= IsNvUpdateRequiredForForm(Form
);
1802 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1809 Update the NvUpdateRequired flag for a form.
1811 @param Form Form data structure.
1815 IsNvUpdateRequiredForForm (
1816 IN FORM_BROWSER_FORM
*Form
1820 FORM_BROWSER_STATEMENT
*Statement
;
1822 Link
= GetFirstNode (&Form
->StatementListHead
);
1823 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1824 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1826 if (Statement
->ValueChanged
) {
1830 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1837 Find menu which will show next time.
1839 @param Selection On input, Selection tell setup browser the information
1840 about the Selection, form and formset to be displayed.
1841 On output, Selection return the screen item that is selected
1843 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1844 else, we need to exit current formset.
1846 @retval TRUE Exit current form.
1847 @retval FALSE User press ESC and keep in current form.
1851 IN OUT UI_MENU_SELECTION
*Selection
,
1852 IN BROWSER_SETTING_SCOPE SettingLevel
1855 FORM_ENTRY_INFO
*CurrentMenu
;
1856 FORM_ENTRY_INFO
*ParentMenu
;
1857 BROWSER_SETTING_SCOPE Scope
;
1859 CurrentMenu
= Selection
->CurrentMenu
;
1860 Scope
= FormSetLevel
;
1862 ParentMenu
= UiFindParentMenu(CurrentMenu
, SettingLevel
);
1863 while (ParentMenu
!= NULL
&& !ValidateHiiHandle(ParentMenu
->HiiHandle
)) {
1864 ParentMenu
= UiFindParentMenu(ParentMenu
, SettingLevel
);
1867 if (ParentMenu
!= NULL
) {
1868 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1871 Scope
= FormSetLevel
;
1876 // Form Level Check whether the data is changed.
1878 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1879 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1880 if (!ProcessChangedData(Selection
, gBrowserSettingScope
)) {
1885 if (ParentMenu
!= NULL
) {
1887 // ParentMenu is found. Then, go to it.
1889 if (Scope
== FormLevel
) {
1890 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
1892 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1893 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1894 Selection
->Handle
= ParentMenu
->HiiHandle
;
1897 Selection
->Statement
= NULL
;
1899 Selection
->FormId
= ParentMenu
->FormId
;
1900 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1903 // Clear highlight record for this menu
1905 CurrentMenu
->QuestionId
= 0;
1910 // Current in root page, exit the SendForm
1912 Selection
->Action
= UI_ACTION_EXIT
;
1918 Reconnect the controller.
1920 @param DriverHandle The controller handle which need to be reconnect.
1922 @retval TRUE do the reconnect behavior success.
1923 @retval FALSE do the reconnect behavior failed.
1927 ReconnectController (
1928 IN EFI_HANDLE DriverHandle
1933 Status
= gBS
->DisconnectController(DriverHandle
, NULL
, NULL
);
1934 if (!EFI_ERROR (Status
)) {
1935 Status
= gBS
->ConnectController(DriverHandle
, NULL
, NULL
, TRUE
);
1938 return Status
== EFI_SUCCESS
;
1942 Call the call back function for the question and process the return action.
1944 @param Selection On input, Selection tell setup browser the information
1945 about the Selection, form and formset to be displayed.
1946 On output, Selection return the screen item that is selected
1948 @param FormSet The formset this question belong to.
1949 @param Form The form this question belong to.
1950 @param Question The Question which need to call.
1951 @param Action The action request.
1952 @param SkipSaveOrDiscard Whether skip save or discard action.
1954 @retval EFI_SUCCESS The call back function executes successfully.
1955 @return Other value if the call back function failed to execute.
1958 ProcessCallBackFunction (
1959 IN OUT UI_MENU_SELECTION
*Selection
,
1960 IN FORM_BROWSER_FORMSET
*FormSet
,
1961 IN FORM_BROWSER_FORM
*Form
,
1962 IN FORM_BROWSER_STATEMENT
*Question
,
1963 IN EFI_BROWSER_ACTION Action
,
1964 IN BOOLEAN SkipSaveOrDiscard
1968 EFI_STATUS InternalStatus
;
1969 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1970 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1971 EFI_HII_VALUE
*HiiValue
;
1972 EFI_IFR_TYPE_VALUE
*TypeValue
;
1973 FORM_BROWSER_STATEMENT
*Statement
;
1974 BOOLEAN SubmitFormIsRequired
;
1975 BOOLEAN DiscardFormIsRequired
;
1978 BROWSER_SETTING_SCOPE SettingLevel
;
1979 EFI_IFR_TYPE_VALUE BackUpValue
;
1980 UINT8
*BackUpBuffer
;
1983 ConfigAccess
= FormSet
->ConfigAccess
;
1984 SubmitFormIsRequired
= FALSE
;
1985 SettingLevel
= FormSetLevel
;
1986 DiscardFormIsRequired
= FALSE
;
1988 Status
= EFI_SUCCESS
;
1989 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1990 BackUpBuffer
= NULL
;
1992 if (ConfigAccess
== NULL
) {
1996 Link
= GetFirstNode (&Form
->StatementListHead
);
1997 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1998 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1999 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2002 // if Question != NULL, only process the question. Else, process all question in this form.
2004 if ((Question
!= NULL
) && (Statement
!= Question
)) {
2008 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2013 // Check whether Statement is disabled.
2015 if (Statement
->Expression
!= NULL
) {
2016 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
2021 HiiValue
= &Statement
->HiiValue
;
2022 TypeValue
= &HiiValue
->Value
;
2023 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2025 // For OrderedList, passing in the value buffer to Callback()
2027 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2031 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2033 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2034 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2035 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
, Statement
->BufferValue
);
2036 ASSERT (BackUpBuffer
!= NULL
);
2038 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2042 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2043 Status
= ConfigAccess
->Callback (
2046 Statement
->QuestionId
,
2051 if (!EFI_ERROR (Status
)) {
2053 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2055 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2056 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2057 ASSERT (NewString
!= NULL
);
2059 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2060 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2061 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2062 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2064 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2066 FreePool (NewString
);
2070 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2073 case EFI_BROWSER_ACTION_CHANGED
:
2074 switch (ActionRequest
) {
2075 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2076 DiscardFormIsRequired
= TRUE
;
2077 gResetRequiredFormLevel
= TRUE
;
2078 gResetRequiredSystemLevel
= TRUE
;
2082 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2083 SubmitFormIsRequired
= TRUE
;
2087 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2088 DiscardFormIsRequired
= TRUE
;
2092 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2093 SubmitFormIsRequired
= TRUE
;
2094 SettingLevel
= FormLevel
;
2098 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2099 DiscardFormIsRequired
= TRUE
;
2100 SettingLevel
= FormLevel
;
2104 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2105 SubmitFormIsRequired
= TRUE
;
2106 SettingLevel
= FormLevel
;
2109 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2110 DiscardFormIsRequired
= TRUE
;
2111 SettingLevel
= FormLevel
;
2114 case EFI_BROWSER_ACTION_REQUEST_RECONNECT
:
2115 gCallbackReconnect
= TRUE
;
2123 case EFI_BROWSER_ACTION_CHANGING
:
2125 // Do the question validation.
2127 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2128 if (!EFI_ERROR (Status
)) {
2130 //check whether the question value changed compared with edit buffer before updating edit buffer
2131 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2133 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2135 // According the spec, return value from call back of "changing" and
2136 // "retrieve" should update to the question's temp buffer.
2138 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2142 case EFI_BROWSER_ACTION_RETRIEVE
:
2144 // According the spec, return value from call back of "changing" and
2145 // "retrieve" should update to the question's temp buffer.
2147 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2155 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2156 // then the browser will use the value passed to Callback() and ignore the
2157 // value returned by Callback().
2159 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2160 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2161 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
);
2163 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2167 // Do the question validation.
2169 InternalStatus
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2170 if (!EFI_ERROR (InternalStatus
)) {
2172 //check whether the question value changed compared with edit buffer before updating edit buffer
2173 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2175 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2176 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2181 // According the spec, return fail from call back of "changing" and
2182 // "retrieve", should restore the question's value.
2184 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) {
2185 if (Statement
->Storage
!= NULL
) {
2186 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2187 } else if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
2188 ProcessCallBackFunction (Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2192 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2193 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2196 if (Status
== EFI_UNSUPPORTED
) {
2198 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2200 Status
= EFI_SUCCESS
;
2204 if (BackUpBuffer
!= NULL
) {
2205 FreePool (BackUpBuffer
);
2209 // If Question != NULL, means just process one question
2210 // and if code reach here means this question has finished
2211 // processing, so just break.
2213 if (Question
!= NULL
) {
2218 if (gCallbackReconnect
&& (EFI_BROWSER_ACTION_CHANGED
== Action
)) {
2220 // Confirm changes with user first.
2222 if (IsNvUpdateRequiredForFormSet(FormSet
)) {
2223 if (BROWSER_ACTION_DISCARD
== PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES
, NULL
, NULL
, NULL
)) {
2224 gCallbackReconnect
= FALSE
;
2225 DiscardFormIsRequired
= TRUE
;
2227 SubmitFormIsRequired
= TRUE
;
2230 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED
, NULL
, NULL
, NULL
);
2234 // Exit current formset before do the reconnect.
2237 SettingLevel
= FormSetLevel
;
2240 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2241 SubmitForm (FormSet
, Form
, SettingLevel
);
2244 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2245 DiscardForm (FormSet
, Form
, SettingLevel
);
2249 FindNextMenu (Selection
, SettingLevel
);
2256 Call the retrieve type call back function for one question to get the initialize data.
2258 This function only used when in the initialize stage, because in this stage, the
2259 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2261 @param ConfigAccess The config access protocol produced by the hii driver.
2262 @param Statement The Question which need to call.
2263 @param FormSet The formset this question belong to.
2265 @retval EFI_SUCCESS The call back function executes successfully.
2266 @return Other value if the call back function failed to execute.
2269 ProcessRetrieveForQuestion (
2270 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2271 IN FORM_BROWSER_STATEMENT
*Statement
,
2272 IN FORM_BROWSER_FORMSET
*FormSet
2276 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2277 EFI_HII_VALUE
*HiiValue
;
2278 EFI_IFR_TYPE_VALUE
*TypeValue
;
2281 Status
= EFI_SUCCESS
;
2282 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2284 if (((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) || ConfigAccess
== NULL
) {
2285 return EFI_UNSUPPORTED
;
2288 HiiValue
= &Statement
->HiiValue
;
2289 TypeValue
= &HiiValue
->Value
;
2290 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2292 // For OrderedList, passing in the value buffer to Callback()
2294 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2297 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2298 Status
= ConfigAccess
->Callback (
2300 EFI_BROWSER_ACTION_RETRIEVE
,
2301 Statement
->QuestionId
,
2306 if (!EFI_ERROR (Status
) && HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2307 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2308 ASSERT (NewString
!= NULL
);
2310 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2311 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2312 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2313 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2315 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2317 FreePool (NewString
);
2324 The worker function that send the displays to the screen. On output,
2325 the selection made by user is returned.
2327 @param Selection On input, Selection tell setup browser the information
2328 about the Selection, form and formset to be displayed.
2329 On output, Selection return the screen item that is selected
2332 @retval EFI_SUCCESS The page is displayed successfully.
2333 @return Other value if the page failed to be diplayed.
2338 IN OUT UI_MENU_SELECTION
*Selection
2343 EFI_HANDLE NotifyHandle
;
2344 FORM_BROWSER_STATEMENT
*Statement
;
2345 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2347 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2350 // Register notify for Form package update
2352 Status
= mHiiDatabase
->RegisterPackageNotify (
2354 EFI_HII_PACKAGE_FORMS
,
2357 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2360 if (EFI_ERROR (Status
)) {
2365 // Initialize current settings of Questions in this FormSet
2367 InitializeCurrentSetting (Selection
->FormSet
);
2370 // Initilize Action field.
2372 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2375 // Clean the mCurFakeQestId value is formset refreshed.
2382 // Reset Status to prevent the next break from returning incorrect error status.
2384 Status
= EFI_SUCCESS
;
2387 // IFR is updated, force to reparse the IFR binary
2388 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and
2389 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.
2391 if (mHiiPackageListUpdated
) {
2392 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2393 mHiiPackageListUpdated
= FALSE
;
2398 // Initialize Selection->Form
2400 if (Selection
->FormId
== 0) {
2402 // Zero FormId indicates display the first Form in a FormSet
2404 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2406 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2407 Selection
->FormId
= Selection
->Form
->FormId
;
2409 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2412 if (Selection
->Form
== NULL
) {
2414 // No Form to display
2416 Status
= EFI_NOT_FOUND
;
2421 // Check Form is suppressed.
2423 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2424 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2426 // Form is suppressed.
2428 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
2429 Status
= EFI_NOT_FOUND
;
2435 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2436 // for each question with callback flag.
2437 // New form may be the first form, or the different form after another form close.
2439 if (((Selection
->Handle
!= mCurrentHiiHandle
) ||
2440 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2441 (Selection
->FormId
!= mCurrentFormId
))) {
2443 // Update Retrieve flag.
2445 mFinishRetrieveCall
= FALSE
;
2448 // Keep current form information
2450 mCurrentHiiHandle
= Selection
->Handle
;
2451 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2452 mCurrentFormId
= Selection
->FormId
;
2454 if (ConfigAccess
!= NULL
) {
2455 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2456 if (EFI_ERROR (Status
)) {
2461 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2463 if (mHiiPackageListUpdated
) {
2464 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2465 mHiiPackageListUpdated
= FALSE
;
2472 // Load Questions' Value for display
2474 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2475 if (EFI_ERROR (Status
)) {
2479 if (!mFinishRetrieveCall
) {
2481 // Finish call RETRIEVE callback for this form.
2483 mFinishRetrieveCall
= TRUE
;
2485 if (ConfigAccess
!= NULL
) {
2486 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2487 if (EFI_ERROR (Status
)) {
2492 // IFR is updated during callback of open form, force to reparse the IFR binary
2494 if (mHiiPackageListUpdated
) {
2495 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2496 mHiiPackageListUpdated
= FALSE
;
2505 Status
= DisplayForm ();
2506 if (EFI_ERROR (Status
)) {
2511 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2513 Statement
= Selection
->Statement
;
2514 if (Statement
!= NULL
) {
2515 if ((ConfigAccess
!= NULL
) &&
2516 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2517 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2518 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2519 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2521 // Process dynamic update ref opcode.
2523 if (!EFI_ERROR (Status
)) {
2524 Status
= ProcessGotoOpCode(Statement
, Selection
);
2528 // Callback return error status or status return from process goto opcode.
2530 if (EFI_ERROR (Status
)) {
2532 // Cross reference will not be taken, restore all essential field
2534 Selection
->Handle
= mCurrentHiiHandle
;
2535 CopyMem (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
, sizeof (EFI_GUID
));
2536 Selection
->FormId
= mCurrentFormId
;
2537 Selection
->QuestionId
= 0;
2538 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2543 if (!EFI_ERROR (Status
) &&
2544 (Statement
->Operand
!= EFI_IFR_REF_OP
) &&
2545 ((Statement
->Storage
== NULL
) || (Statement
->Storage
!= NULL
&& Statement
->ValueChanged
))) {
2547 // Only question value has been changed, browser will trig CHANGED callback.
2549 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2551 //check whether the question value changed compared with buffer value
2552 //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen
2554 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2558 // Do the question validation.
2560 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2561 if (!EFI_ERROR (Status
) && (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2562 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2564 // Verify whether question value has checked, update the ValueChanged flag in Question.
2566 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2571 // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage
2572 // and process question success till here, trig the gResetFlag/gFlagReconnect.
2574 if ((Status
== EFI_SUCCESS
) &&
2575 (Statement
->Storage
== NULL
)) {
2576 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2577 gResetRequiredFormLevel
= TRUE
;
2578 gResetRequiredSystemLevel
= TRUE
;
2581 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2582 gFlagReconnect
= TRUE
;
2588 // Check whether Exit flag is TRUE.
2590 if (gExitRequired
) {
2591 switch (gBrowserSettingScope
) {
2593 Selection
->Action
= UI_ACTION_EXIT
;
2598 FindNextMenu (Selection
, gBrowserSettingScope
);
2605 gExitRequired
= FALSE
;
2609 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2610 // for each question with callback flag.
2612 if ((ConfigAccess
!= NULL
) &&
2613 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2614 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2615 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2616 (Selection
->FormId
!= mCurrentFormId
))) {
2618 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2619 if (EFI_ERROR (Status
)) {
2623 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2627 // Reset current form information to the initial setting when error happens or form exit.
2629 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2630 mCurrentHiiHandle
= NULL
;
2631 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2636 // Unregister notify for Form package update
2638 mHiiDatabase
->UnregisterPackageNotify (