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
;
22 BOOLEAN mDynamicFormUpdated
= FALSE
;
25 Check whether the ConfigAccess protocol is available.
27 @param FormSet FormSet of which the ConfigAcces protocol need to be checked.
29 @retval EFI_SUCCESS The function executed successfully.
34 IN FORM_BROWSER_FORMSET
*FormSet
39 Status
= gBS
->HandleProtocol (
40 FormSet
->DriverHandle
,
41 &gEfiHiiConfigAccessProtocolGuid
,
42 (VOID
**) &FormSet
->ConfigAccess
44 if (EFI_ERROR (Status
)) {
46 // Configuration Driver don't attach ConfigAccess protocol to its HII package
47 // list, then there will be no configuration action required.
48 // Or the ConfigAccess protocol has been uninstalled.
50 FormSet
->ConfigAccess
= NULL
;
57 Evaluate all expressions in a Form.
59 @param FormSet FormSet this Form belongs to.
62 @retval EFI_SUCCESS The expression evaluated successfuly
66 EvaluateFormExpressions (
67 IN FORM_BROWSER_FORMSET
*FormSet
,
68 IN FORM_BROWSER_FORM
*Form
73 FORM_EXPRESSION
*Expression
;
75 Link
= GetFirstNode (&Form
->ExpressionListHead
);
76 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
77 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
78 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
80 if (Expression
->Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
||
81 Expression
->Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
||
82 Expression
->Type
== EFI_HII_EXPRESSION_WARNING_IF
||
83 Expression
->Type
== EFI_HII_EXPRESSION_WRITE
||
84 (Expression
->Type
== EFI_HII_EXPRESSION_READ
&& Form
->FormType
!= STANDARD_MAP_FORM_TYPE
)) {
86 // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
91 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
92 if (EFI_ERROR (Status
)) {
101 Base on the opcode buffer info to get the display statement.
103 @param OpCode The input opcode buffer for this statement.
105 @retval Statement The statement use this opcode buffer.
108 FORM_DISPLAY_ENGINE_STATEMENT
*
109 GetDisplayStatement (
110 IN EFI_IFR_OP_HEADER
*OpCode
113 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
116 Link
= GetFirstNode (&gDisplayFormData
.StatementListHead
);
117 while (!IsNull (&gDisplayFormData
.StatementListHead
, Link
)) {
118 DisplayStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
120 if (DisplayStatement
->OpCode
== OpCode
) {
121 return DisplayStatement
;
123 Link
= GetNextNode (&gDisplayFormData
.StatementListHead
, Link
);
130 Free the refresh event list.
139 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
141 while (!IsListEmpty (&mRefreshEventList
)) {
142 Link
= GetFirstNode (&mRefreshEventList
);
143 EventNode
= FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link
);
144 RemoveEntryList (&EventNode
->Link
);
146 gBS
->CloseEvent (EventNode
->RefreshEvent
);
148 FreePool (EventNode
);
153 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
156 @param Statement The statement need to check.
161 IN OUT FORM_BROWSER_STATEMENT
*Statement
164 GetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
167 // Reset FormPackage update flag
169 mHiiPackageListUpdated
= FALSE
;
172 // Question value may be changed, need invoke its Callback()
174 ProcessCallBackFunction (gCurrentSelection
, gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
176 if (mHiiPackageListUpdated
) {
178 // Package list is updated, force to reparse IFR binary of target Formset
180 mHiiPackageListUpdated
= FALSE
;
181 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
186 Refresh the question which has refresh guid event attribute.
188 @param Event The event which has this function related.
189 @param Context The input context info related to this event or the status code return to the caller.
193 RefreshEventNotifyForStatement(
198 FORM_BROWSER_STATEMENT
*Statement
;
200 Statement
= (FORM_BROWSER_STATEMENT
*)Context
;
201 UpdateStatement(Statement
);
202 gBS
->SignalEvent (mValueChangedEvent
);
206 Refresh the questions within this form.
208 @param Event The event which has this function related.
209 @param Context The input context info related to this event or the status code return to the caller.
213 RefreshEventNotifyForForm(
218 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
220 gBS
->SignalEvent (mValueChangedEvent
);
224 Create refresh hook event for statement which has refresh event or interval.
226 @param Statement The statement need to check.
230 CreateRefreshEventForStatement (
231 IN FORM_BROWSER_STATEMENT
*Statement
235 EFI_EVENT RefreshEvent
;
236 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
239 // If question has refresh guid, create the notify function.
241 Status
= gBS
->CreateEventEx (
244 RefreshEventNotifyForStatement
,
246 &Statement
->RefreshGuid
,
248 ASSERT_EFI_ERROR (Status
);
250 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
251 ASSERT (EventNode
!= NULL
);
252 EventNode
->RefreshEvent
= RefreshEvent
;
253 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
257 Create refresh hook event for form which has refresh event or interval.
259 @param Form The form need to check.
263 CreateRefreshEventForForm (
264 IN FORM_BROWSER_FORM
*Form
268 EFI_EVENT RefreshEvent
;
269 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
272 // If question has refresh guid, create the notify function.
274 Status
= gBS
->CreateEventEx (
277 RefreshEventNotifyForForm
,
281 ASSERT_EFI_ERROR (Status
);
283 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
284 ASSERT (EventNode
!= NULL
);
285 EventNode
->RefreshEvent
= RefreshEvent
;
286 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
291 Initialize the Display statement structure data.
293 @param DisplayStatement Pointer to the display Statement data strucure.
294 @param Statement The statement need to check.
297 InitializeDisplayStatement (
298 IN OUT FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
,
299 IN FORM_BROWSER_STATEMENT
*Statement
303 QUESTION_OPTION
*Option
;
304 DISPLAY_QUESTION_OPTION
*DisplayOption
;
305 FORM_DISPLAY_ENGINE_STATEMENT
*ParentStatement
;
307 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
308 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
309 DisplayStatement
->OpCode
= Statement
->OpCode
;
310 InitializeListHead (&DisplayStatement
->NestStatementList
);
311 InitializeListHead (&DisplayStatement
->OptionListHead
);
313 if ((EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) == ExpressGrayOut
) || Statement
->Locked
) {
314 DisplayStatement
->Attribute
|= HII_DISPLAY_GRAYOUT
;
316 if ((Statement
->ValueExpression
!= NULL
) || ((Statement
->QuestionFlags
& EFI_IFR_FLAG_READ_ONLY
) != 0)) {
317 DisplayStatement
->Attribute
|= HII_DISPLAY_READONLY
;
321 // Initilize the option list in statement.
323 Link
= GetFirstNode (&Statement
->OptionListHead
);
324 while (!IsNull (&Statement
->OptionListHead
, Link
)) {
325 Option
= QUESTION_OPTION_FROM_LINK (Link
);
326 Link
= GetNextNode (&Statement
->OptionListHead
, Link
);
327 if ((Option
->SuppressExpression
!= NULL
) &&
328 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressSuppress
))) {
332 DisplayOption
= AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION
));
333 ASSERT (DisplayOption
!= NULL
);
335 DisplayOption
->ImageId
= Option
->ImageId
;
336 DisplayOption
->Signature
= DISPLAY_QUESTION_OPTION_SIGNATURE
;
337 DisplayOption
->OptionOpCode
= Option
->OpCode
;
338 InsertTailList(&DisplayStatement
->OptionListHead
, &DisplayOption
->Link
);
341 CopyMem (&DisplayStatement
->CurrentValue
, &Statement
->HiiValue
, sizeof (EFI_HII_VALUE
));
344 // Some special op code need an extra buffer to save the data.
345 // Such as string, password, orderedlist...
347 if (Statement
->BufferValue
!= NULL
) {
349 // Ordered list opcode may not initilized, get default value here.
351 if (Statement
->OpCode
->OpCode
== EFI_IFR_ORDERED_LIST_OP
&& GetArrayData (Statement
->BufferValue
, Statement
->ValueType
, 0) == 0) {
352 GetQuestionDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, 0);
355 DisplayStatement
->CurrentValue
.Buffer
= AllocateCopyPool(Statement
->StorageWidth
,Statement
->BufferValue
);
356 DisplayStatement
->CurrentValue
.BufferLen
= Statement
->StorageWidth
;
359 DisplayStatement
->SettingChangedFlag
= Statement
->ValueChanged
;
362 // Get the highlight statement for current form.
364 if (((gCurrentSelection
->QuestionId
!= 0) && (Statement
->QuestionId
== gCurrentSelection
->QuestionId
)) ||
365 ((mCurFakeQestId
!= 0) && (Statement
->FakeQuestionId
== mCurFakeQestId
))) {
366 gDisplayFormData
.HighLightedStatement
= DisplayStatement
;
370 // Create the refresh event process function.
372 if (!IsZeroGuid (&Statement
->RefreshGuid
)) {
373 CreateRefreshEventForStatement (Statement
);
377 // For RTC type of date/time, set default refresh interval to be 1 second.
379 if ((Statement
->Operand
== EFI_IFR_DATE_OP
|| Statement
->Operand
== EFI_IFR_TIME_OP
) && Statement
->Storage
== NULL
) {
380 Statement
->RefreshInterval
= 1;
384 // Create the refresh guid hook event.
385 // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
387 if ((!IsZeroGuid (&Statement
->RefreshGuid
)) || (Statement
->RefreshInterval
!= 0)) {
388 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
392 // Save the password check function for later use.
394 if (Statement
->Operand
== EFI_IFR_PASSWORD_OP
) {
395 DisplayStatement
->PasswordCheck
= PasswordCheck
;
399 // If this statement is nest in the subtitle, insert to the host statement.
400 // else insert to the form it belongs to.
402 if (Statement
->ParentStatement
!= NULL
) {
403 ParentStatement
= GetDisplayStatement(Statement
->ParentStatement
->OpCode
);
404 ASSERT (ParentStatement
!= NULL
);
405 InsertTailList(&ParentStatement
->NestStatementList
, &DisplayStatement
->DisplayLink
);
407 InsertTailList(&gDisplayFormData
.StatementListHead
, &DisplayStatement
->DisplayLink
);
412 Process for the refresh interval statement.
414 @param Event The Event need to be process
415 @param Context The context of the event.
420 RefreshIntervalProcess (
425 FORM_BROWSER_STATEMENT
*Statement
;
428 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
429 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
430 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
431 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
433 if (Statement
->RefreshInterval
== 0) {
437 UpdateStatement(Statement
);
440 gBS
->SignalEvent (mValueChangedEvent
);
445 Make a copy of the global hotkey info.
453 BROWSER_HOT_KEY
*HotKey
;
454 BROWSER_HOT_KEY
*CopyKey
;
457 Link
= GetFirstNode (&gBrowserHotKeyList
);
458 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
459 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
461 CopyKey
= AllocateCopyPool(sizeof (BROWSER_HOT_KEY
), HotKey
);
462 ASSERT (CopyKey
!= NULL
);
463 CopyKey
->KeyData
= AllocateCopyPool(sizeof (EFI_INPUT_KEY
), HotKey
->KeyData
);
464 ASSERT (CopyKey
->KeyData
!= NULL
);
465 CopyKey
->HelpString
= AllocateCopyPool(StrSize (HotKey
->HelpString
), HotKey
->HelpString
);
466 ASSERT (CopyKey
->HelpString
!= NULL
);
468 InsertTailList(&gDisplayFormData
.HotKeyListHead
, &CopyKey
->Link
);
470 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
476 Get the extra question attribute from override question list.
478 @param QuestionId The question id for this request question.
480 @retval The attribute for this question or NULL if not found this
481 question in the list.
485 ProcessQuestionExtraAttr (
486 IN EFI_QUESTION_ID QuestionId
490 QUESTION_ATTRIBUTE_OVERRIDE
*QuestionDesc
;
493 // Return HII_DISPLAY_NONE if input a invalid question id.
495 if (QuestionId
== 0) {
496 return HII_DISPLAY_NONE
;
499 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
500 while (!IsNull (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
)) {
501 QuestionDesc
= FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link
);
502 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
, Link
);
504 if ((QuestionDesc
->QuestionId
== QuestionId
) &&
505 (QuestionDesc
->FormId
== gCurrentSelection
->FormId
) &&
506 (QuestionDesc
->HiiHandle
== gCurrentSelection
->Handle
) &&
507 CompareGuid (&QuestionDesc
->FormSetGuid
, &gCurrentSelection
->FormSetGuid
)) {
508 return QuestionDesc
->Attribute
;
512 return HII_DISPLAY_NONE
;
517 Enum all statement in current form, find all the statement can be display and
518 add to the display form.
522 AddStatementToDisplayForm (
528 FORM_BROWSER_STATEMENT
*Statement
;
529 FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
;
530 UINT8 MinRefreshInterval
;
531 EFI_EVENT RefreshIntervalEvent
;
532 FORM_BROWSER_REFRESH_EVENT_NODE
*EventNode
;
533 BOOLEAN FormEditable
;
534 UINT32 ExtraAttribute
;
536 MinRefreshInterval
= 0;
537 FormEditable
= FALSE
;
540 // Process the statement outside the form, these statements are not recognized
543 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->StatementListOSF
);
544 while (!IsNull (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
)) {
545 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
546 Link
= GetNextNode (&gCurrentSelection
->FormSet
->StatementListOSF
, Link
);
548 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
549 ASSERT (DisplayStatement
!= NULL
);
550 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
551 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
552 DisplayStatement
->OpCode
= Statement
->OpCode
;
554 InitializeListHead (&DisplayStatement
->NestStatementList
);
555 InitializeListHead (&DisplayStatement
->OptionListHead
);
557 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
561 // treat formset as statement outside the form,get its opcode.
563 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
564 ASSERT (DisplayStatement
!= NULL
);
566 DisplayStatement
->Signature
= FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE
;
567 DisplayStatement
->Version
= FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1
;
568 DisplayStatement
->OpCode
= gCurrentSelection
->FormSet
->OpCode
;
570 InitializeListHead (&DisplayStatement
->NestStatementList
);
571 InitializeListHead (&DisplayStatement
->OptionListHead
);
573 InsertTailList(&gDisplayFormData
.StatementListOSF
, &DisplayStatement
->DisplayLink
);
576 // Process the statement in this form.
578 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
579 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
580 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
581 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
584 // This statement can't be show, skip it.
586 if (EvaluateExpressionList(Statement
->Expression
, FALSE
, NULL
, NULL
) > ExpressGrayOut
) {
591 // Check the extra attribute.
593 ExtraAttribute
= ProcessQuestionExtraAttr (Statement
->QuestionId
);
594 if ((ExtraAttribute
& HII_DISPLAY_SUPPRESS
) != 0) {
598 DisplayStatement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
599 ASSERT (DisplayStatement
!= NULL
);
602 // Initialize this statement and add it to the display form.
604 InitializeDisplayStatement(DisplayStatement
, Statement
);
607 // Set the extra attribute.
609 DisplayStatement
->Attribute
|= ExtraAttribute
;
611 if (Statement
->Storage
!= NULL
) {
616 // Get the minimal refresh interval value for later use.
618 if ((Statement
->RefreshInterval
!= 0) &&
619 (MinRefreshInterval
== 0 || Statement
->RefreshInterval
< MinRefreshInterval
)) {
620 MinRefreshInterval
= Statement
->RefreshInterval
;
625 // Create the periodic timer for refresh interval statement.
627 if (MinRefreshInterval
!= 0) {
628 Status
= gBS
->CreateEvent (EVT_TIMER
| EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, RefreshIntervalProcess
, NULL
, &RefreshIntervalEvent
);
629 ASSERT_EFI_ERROR (Status
);
630 Status
= gBS
->SetTimer (RefreshIntervalEvent
, TimerPeriodic
, MinRefreshInterval
* ONE_SECOND
);
631 ASSERT_EFI_ERROR (Status
);
633 EventNode
= AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE
));
634 ASSERT (EventNode
!= NULL
);
635 EventNode
->RefreshEvent
= RefreshIntervalEvent
;
636 InsertTailList(&mRefreshEventList
, &EventNode
->Link
);
640 // Create the refresh event process function for Form.
642 if (!IsZeroGuid (&gCurrentSelection
->Form
->RefreshGuid
)) {
643 CreateRefreshEventForForm (gCurrentSelection
->Form
);
644 if (gDisplayFormData
.FormRefreshEvent
== NULL
) {
645 gDisplayFormData
.FormRefreshEvent
= mValueChangedEvent
;
650 // Update hotkey list field.
652 if (gBrowserSettingScope
== SystemLevel
|| FormEditable
) {
659 Initialize the SettingChangedFlag variable in the display form.
663 UpdateDataChangedFlag (
668 FORM_BROWSER_FORMSET
*LocalFormSet
;
670 gDisplayFormData
.SettingChangedFlag
= FALSE
;
672 if (IsNvUpdateRequiredForForm (gCurrentSelection
->Form
)) {
673 gDisplayFormData
.SettingChangedFlag
= TRUE
;
678 // Base on the system level to check whether need to show the NV flag.
680 switch (gBrowserSettingScope
) {
683 // Check the maintain list to see whether there is any change.
685 Link
= GetFirstNode (&gBrowserFormSetList
);
686 while (!IsNull (&gBrowserFormSetList
, Link
)) {
687 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
688 if (IsNvUpdateRequiredForFormSet(LocalFormSet
)) {
689 gDisplayFormData
.SettingChangedFlag
= TRUE
;
692 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
697 if (IsNvUpdateRequiredForFormSet(gCurrentSelection
->FormSet
)) {
698 gDisplayFormData
.SettingChangedFlag
= TRUE
;
710 Initialize the Display form structure data.
714 InitializeDisplayFormData (
720 gDisplayFormData
.Signature
= FORM_DISPLAY_ENGINE_FORM_SIGNATURE
;
721 gDisplayFormData
.Version
= FORM_DISPLAY_ENGINE_VERSION_1
;
722 gDisplayFormData
.ImageId
= 0;
723 gDisplayFormData
.AnimationId
= 0;
725 InitializeListHead (&gDisplayFormData
.StatementListHead
);
726 InitializeListHead (&gDisplayFormData
.StatementListOSF
);
727 InitializeListHead (&gDisplayFormData
.HotKeyListHead
);
729 Status
= gBS
->CreateEvent (
732 EfiEventEmptyFunction
,
736 ASSERT_EFI_ERROR (Status
);
741 Free the kotkey info saved in form data.
749 BROWSER_HOT_KEY
*HotKey
;
752 while (!IsListEmpty (&gDisplayFormData
.HotKeyListHead
)) {
753 Link
= GetFirstNode (&gDisplayFormData
.HotKeyListHead
);
754 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
756 RemoveEntryList (&HotKey
->Link
);
758 FreePool (HotKey
->KeyData
);
759 FreePool (HotKey
->HelpString
);
766 Update the Display form structure data.
770 UpdateDisplayFormData (
774 gDisplayFormData
.FormTitle
= gCurrentSelection
->Form
->FormTitle
;
775 gDisplayFormData
.FormId
= gCurrentSelection
->FormId
;
776 gDisplayFormData
.HiiHandle
= gCurrentSelection
->Handle
;
777 CopyGuid (&gDisplayFormData
.FormSetGuid
, &gCurrentSelection
->FormSetGuid
);
779 gDisplayFormData
.Attribute
= 0;
780 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->ModalForm
? HII_DISPLAY_MODAL
: 0;
781 gDisplayFormData
.Attribute
|= gCurrentSelection
->Form
->Locked
? HII_DISPLAY_LOCK
: 0;
783 gDisplayFormData
.FormRefreshEvent
= NULL
;
784 gDisplayFormData
.HighLightedStatement
= NULL
;
786 UpdateDataChangedFlag ();
788 AddStatementToDisplayForm ();
793 Free the Display Statement structure data.
795 @param StatementList Point to the statement list which need to be free.
800 LIST_ENTRY
*StatementList
804 LIST_ENTRY
*OptionLink
;
805 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
806 DISPLAY_QUESTION_OPTION
*Option
;
809 // Free Statements/Questions
811 while (!IsListEmpty (StatementList
)) {
812 Link
= GetFirstNode (StatementList
);
813 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
818 while (!IsListEmpty (&Statement
->OptionListHead
)) {
819 OptionLink
= GetFirstNode (&Statement
->OptionListHead
);
820 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink
);
821 RemoveEntryList (&Option
->Link
);
826 // Free nest statement List
828 if (!IsListEmpty (&Statement
->NestStatementList
)) {
829 FreeStatementData(&Statement
->NestStatementList
);
832 RemoveEntryList (&Statement
->DisplayLink
);
833 FreePool (Statement
);
839 Free the Display form structure data.
843 FreeDisplayFormData (
847 FreeStatementData (&gDisplayFormData
.StatementListHead
);
848 FreeStatementData (&gDisplayFormData
.StatementListOSF
);
857 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
859 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
861 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
864 FORM_BROWSER_STATEMENT
*
865 GetBrowserStatement (
866 IN FORM_DISPLAY_ENGINE_STATEMENT
*DisplayStatement
869 FORM_BROWSER_STATEMENT
*Statement
;
872 Link
= GetFirstNode (&gCurrentSelection
->Form
->StatementListHead
);
873 while (!IsNull (&gCurrentSelection
->Form
->StatementListHead
, Link
)) {
874 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
876 if (Statement
->OpCode
== DisplayStatement
->OpCode
) {
880 Link
= GetNextNode (&gCurrentSelection
->Form
->StatementListHead
, Link
);
887 Update the ValueChanged status for questions in this form.
889 @param FormSet FormSet data structure.
890 @param Form Form data structure.
894 UpdateStatementStatusForForm (
895 IN FORM_BROWSER_FORMSET
*FormSet
,
896 IN FORM_BROWSER_FORM
*Form
900 FORM_BROWSER_STATEMENT
*Question
;
902 Link
= GetFirstNode (&Form
->StatementListHead
);
903 while (!IsNull (&Form
->StatementListHead
, Link
)) {
904 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
905 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
908 // For password opcode, not set the the value changed flag.
910 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
914 IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
919 Update the ValueChanged status for questions in this formset.
921 @param FormSet FormSet data structure.
925 UpdateStatementStatusForFormSet (
926 IN FORM_BROWSER_FORMSET
*FormSet
930 FORM_BROWSER_FORM
*Form
;
932 Link
= GetFirstNode (&FormSet
->FormListHead
);
933 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
934 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
935 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
937 UpdateStatementStatusForForm (FormSet
, Form
);
942 Update the ValueChanged status for questions.
944 @param FormSet FormSet data structure.
945 @param Form Form data structure.
946 @param SettingScope Setting Scope for Default action.
950 UpdateStatementStatus (
951 IN FORM_BROWSER_FORMSET
*FormSet
,
952 IN FORM_BROWSER_FORM
*Form
,
953 IN BROWSER_SETTING_SCOPE SettingScope
957 FORM_BROWSER_FORMSET
*LocalFormSet
;
959 switch (SettingScope
) {
961 Link
= GetFirstNode (&gBrowserFormSetList
);
962 while (!IsNull (&gBrowserFormSetList
, Link
)) {
963 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
964 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
965 if (!ValidateFormSet(LocalFormSet
)) {
969 UpdateStatementStatusForFormSet (LocalFormSet
);
974 UpdateStatementStatusForFormSet (FormSet
);
978 UpdateStatementStatusForForm (FormSet
, Form
);
988 Process the action request in user input.
990 @param Action The user input action request info.
991 @param DefaultId The user input default Id info.
993 @retval EFI_SUCESSS This function always return successfully for now.
1003 // This is caused by use press ESC, and it should not combine with other action type.
1005 if ((Action
& BROWSER_ACTION_FORM_EXIT
) == BROWSER_ACTION_FORM_EXIT
) {
1006 FindNextMenu (gCurrentSelection
, FormLevel
);
1011 // Below is normal hotkey trigged action, these action maybe combine with each other.
1013 if ((Action
& BROWSER_ACTION_DISCARD
) == BROWSER_ACTION_DISCARD
) {
1014 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1017 if ((Action
& BROWSER_ACTION_DEFAULT
) == BROWSER_ACTION_DEFAULT
) {
1018 ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1019 UpdateStatementStatus (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1022 if ((Action
& BROWSER_ACTION_SUBMIT
) == BROWSER_ACTION_SUBMIT
) {
1023 SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1026 if ((Action
& BROWSER_ACTION_RESET
) == BROWSER_ACTION_RESET
) {
1027 gResetRequiredFormLevel
= TRUE
;
1028 gResetRequiredSystemLevel
= TRUE
;
1031 if ((Action
& BROWSER_ACTION_EXIT
) == BROWSER_ACTION_EXIT
) {
1033 // Form Exit without saving, Similar to ESC Key.
1034 // FormSet Exit without saving, Exit SendForm.
1035 // System Exit without saving, CallExitHandler and Exit SendForm.
1037 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
1038 if (gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) {
1039 FindNextMenu (gCurrentSelection
, gBrowserSettingScope
);
1040 } else if (gBrowserSettingScope
== SystemLevel
) {
1041 if (ExitHandlerFunction
!= NULL
) {
1042 ExitHandlerFunction ();
1044 gCurrentSelection
->Action
= UI_ACTION_EXIT
;
1052 Check whether the formset guid is in this Hii package list.
1054 @param HiiHandle The HiiHandle for this HII package list.
1055 @param FormSetGuid The formset guid for the request formset.
1057 @retval TRUE Find the formset guid.
1058 @retval FALSE Not found the formset guid.
1062 GetFormsetGuidFromHiiHandle (
1063 IN EFI_HII_HANDLE HiiHandle
,
1064 IN EFI_GUID
*FormSetGuid
1067 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1071 UINT32 PackageListLength
;
1072 EFI_HII_PACKAGE_HEADER PackageHeader
;
1079 HiiPackageList
= NULL
;
1082 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1083 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1084 HiiPackageList
= AllocatePool (BufferSize
);
1085 ASSERT (HiiPackageList
!= NULL
);
1087 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1089 if (EFI_ERROR (Status
) || HiiPackageList
== NULL
) {
1094 // Get Form package from this HII package List
1096 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1098 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
1100 while (Offset
< PackageListLength
) {
1101 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
1102 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
1103 Offset
+= PackageHeader
.Length
;
1105 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1107 // Search FormSet in this Form Package
1109 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
1110 while (Offset2
< PackageHeader
.Length
) {
1111 OpCodeData
= Package
+ Offset2
;
1113 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
1114 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))){
1120 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
1128 FreePool (HiiPackageList
);
1134 Find HII Handle in the HII database associated with given Device Path.
1136 If DevicePath is NULL, then ASSERT.
1138 @param DevicePath Device Path associated with the HII package list
1140 @param FormsetGuid The formset guid for this formset.
1142 @retval Handle HII package list Handle associated with the Device
1144 @retval NULL Hii Package list handle is not found.
1148 DevicePathToHiiHandle (
1149 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1150 IN EFI_GUID
*FormsetGuid
1154 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
1157 EFI_HANDLE DriverHandle
;
1158 EFI_HII_HANDLE
*HiiHandles
;
1159 EFI_HII_HANDLE HiiHandle
;
1161 ASSERT (DevicePath
!= NULL
);
1163 TmpDevicePath
= DevicePath
;
1165 // Locate Device Path Protocol handle buffer
1167 Status
= gBS
->LocateDevicePath (
1168 &gEfiDevicePathProtocolGuid
,
1172 if (EFI_ERROR (Status
) || !IsDevicePathEnd (TmpDevicePath
)) {
1177 // Retrieve all HII Handles from HII database
1179 HiiHandles
= HiiGetHiiHandles (NULL
);
1180 if (HiiHandles
== NULL
) {
1185 // Search Hii Handle by Driver Handle
1188 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1189 Status
= mHiiDatabase
->GetPackageListHandle (
1194 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1195 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], FormsetGuid
)) {
1196 HiiHandle
= HiiHandles
[Index
];
1200 if (HiiHandle
!= NULL
) {
1206 FreePool (HiiHandles
);
1211 Find HII Handle in the HII database associated with given form set guid.
1213 If FormSetGuid is NULL, then ASSERT.
1215 @param ComparingGuid FormSet Guid associated with the HII package list
1218 @retval Handle HII package list Handle associated with the Device
1220 @retval NULL Hii Package list handle is not found.
1224 FormSetGuidToHiiHandle (
1225 EFI_GUID
*ComparingGuid
1228 EFI_HII_HANDLE
*HiiHandles
;
1229 EFI_HII_HANDLE HiiHandle
;
1232 ASSERT (ComparingGuid
!= NULL
);
1236 // Get all the Hii handles
1238 HiiHandles
= HiiGetHiiHandles (NULL
);
1239 ASSERT (HiiHandles
!= NULL
);
1242 // Search for formset of each class type
1244 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1245 if (GetFormsetGuidFromHiiHandle(HiiHandles
[Index
], ComparingGuid
)) {
1246 HiiHandle
= HiiHandles
[Index
];
1250 if (HiiHandle
!= NULL
) {
1255 FreePool (HiiHandles
);
1261 check how to process the changed data in current form or form set.
1263 @param Selection On input, Selection tell setup browser the information
1264 about the Selection, form and formset to be displayed.
1265 On output, Selection return the screen item that is selected
1268 @param Scope Data save or discard scope, form or formset.
1270 @retval TRUE Success process the changed data, will return to the parent form.
1271 @retval FALSE Reject to process the changed data, will stay at current form.
1274 ProcessChangedData (
1275 IN OUT UI_MENU_SELECTION
*Selection
,
1276 IN BROWSER_SETTING_SCOPE Scope
1283 switch (mFormDisplay
->ConfirmDataChange()) {
1284 case BROWSER_ACTION_DISCARD
:
1285 DiscardForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1288 case BROWSER_ACTION_SUBMIT
:
1289 Status
= SubmitForm (Selection
->FormSet
, Selection
->Form
, Scope
);
1290 if (EFI_ERROR (Status
)) {
1295 case BROWSER_ACTION_NONE
:
1301 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1311 Find parent formset menu(the first menu which has different formset) for current menu.
1312 If not find, just return to the first menu.
1314 @param Selection The selection info.
1319 IN OUT UI_MENU_SELECTION
*Selection
1322 FORM_ENTRY_INFO
*CurrentMenu
;
1323 FORM_ENTRY_INFO
*ParentMenu
;
1325 CurrentMenu
= Selection
->CurrentMenu
;
1326 ParentMenu
= UiFindParentMenu(CurrentMenu
, FormSetLevel
);
1328 if (ParentMenu
!= NULL
) {
1329 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1330 Selection
->Handle
= ParentMenu
->HiiHandle
;
1331 Selection
->FormId
= ParentMenu
->FormId
;
1332 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1334 Selection
->FormId
= CurrentMenu
->FormId
;
1335 Selection
->QuestionId
= CurrentMenu
->QuestionId
;
1338 Selection
->Statement
= NULL
;
1342 Process the goto op code, update the info in the selection structure.
1344 @param Statement The statement belong to goto op code.
1345 @param Selection The selection info.
1347 @retval EFI_SUCCESS The menu process successfully.
1348 @return Other value if the process failed.
1352 IN OUT FORM_BROWSER_STATEMENT
*Statement
,
1353 IN OUT UI_MENU_SELECTION
*Selection
1357 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1358 FORM_BROWSER_FORM
*RefForm
;
1360 EFI_HII_HANDLE HiiHandle
;
1362 Status
= EFI_SUCCESS
;
1367 // Prepare the device path check, get the device path info first.
1369 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0) {
1370 StringPtr
= GetToken (Statement
->HiiValue
.Value
.ref
.DevicePath
, Selection
->FormSet
->HiiHandle
);
1374 // Check whether the device path string is a valid string.
1376 if (Statement
->HiiValue
.Value
.ref
.DevicePath
!= 0 && StringPtr
!= NULL
&& StringPtr
[0] != L
'\0') {
1377 if (Selection
->Form
->ModalForm
) {
1382 // Goto another Hii Package list
1384 if (mPathFromText
!= NULL
) {
1385 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StringPtr
);
1386 if (DevicePath
!= NULL
) {
1387 HiiHandle
= DevicePathToHiiHandle (DevicePath
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1388 FreePool (DevicePath
);
1390 FreePool (StringPtr
);
1393 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1395 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND
, NULL
, NULL
, NULL
);
1396 FreePool (StringPtr
);
1400 if (HiiHandle
!= Selection
->Handle
) {
1402 // Goto another Formset, check for uncommitted data
1404 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1405 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1406 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1412 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1413 Selection
->Handle
= HiiHandle
;
1414 if (Selection
->Handle
== NULL
) {
1416 // If target Hii Handle not found, exit current formset.
1418 FindParentFormSet(Selection
);
1422 CopyMem (&Selection
->FormSetGuid
,&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1423 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1424 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1425 } else if (!IsZeroGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
)) {
1426 if (Selection
->Form
->ModalForm
) {
1429 if (!CompareGuid (&Statement
->HiiValue
.Value
.ref
.FormSetGuid
, &Selection
->FormSetGuid
)) {
1431 // Goto another Formset, check for uncommitted data
1433 if ((gBrowserSettingScope
== FormLevel
|| gBrowserSettingScope
== FormSetLevel
) &&
1434 IsNvUpdateRequiredForFormSet(Selection
->FormSet
)) {
1435 if (!ProcessChangedData(Selection
, FormSetLevel
)) {
1441 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1442 Selection
->Handle
= FormSetGuidToHiiHandle(&Statement
->HiiValue
.Value
.ref
.FormSetGuid
);
1443 if (Selection
->Handle
== NULL
) {
1445 // If target Hii Handle not found, exit current formset.
1447 FindParentFormSet(Selection
);
1451 CopyMem (&Selection
->FormSetGuid
, &Statement
->HiiValue
.Value
.ref
.FormSetGuid
, sizeof (EFI_GUID
));
1452 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1453 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1454 } else if (Statement
->HiiValue
.Value
.ref
.FormId
!= 0) {
1456 // Goto another Form, check for uncommitted data
1458 if (Statement
->HiiValue
.Value
.ref
.FormId
!= Selection
->FormId
) {
1459 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm(Selection
->Form
))) {
1460 if (!ProcessChangedData (Selection
, FormLevel
)) {
1466 RefForm
= IdToForm (Selection
->FormSet
, Statement
->HiiValue
.Value
.ref
.FormId
);
1467 if ((RefForm
!= NULL
) && (RefForm
->SuppressExpression
!= NULL
)) {
1468 if (EvaluateExpressionList(RefForm
->SuppressExpression
, TRUE
, Selection
->FormSet
, RefForm
) != ExpressFalse
) {
1470 // Form is suppressed.
1472 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
1477 Selection
->FormId
= Statement
->HiiValue
.Value
.ref
.FormId
;
1478 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1479 } else if (Statement
->HiiValue
.Value
.ref
.QuestionId
!= 0) {
1480 Selection
->QuestionId
= Statement
->HiiValue
.Value
.ref
.QuestionId
;
1488 Process Question Config.
1490 @param Selection The UI menu selection.
1491 @param Question The Question to be peocessed.
1493 @retval EFI_SUCCESS Question Config process success.
1494 @retval Other Question Config process fail.
1498 ProcessQuestionConfig (
1499 IN UI_MENU_SELECTION
*Selection
,
1500 IN FORM_BROWSER_STATEMENT
*Question
1507 if (Question
->QuestionConfig
== 0) {
1514 ConfigResp
= GetToken (Question
->QuestionConfig
, Selection
->FormSet
->HiiHandle
);
1515 if (ConfigResp
== NULL
) {
1516 return EFI_NOT_FOUND
;
1517 } else if (ConfigResp
[0] == L
'\0') {
1522 // Send config to Configuration Driver
1524 Status
= mHiiConfigRouting
->RouteConfig (
1535 Process the user input data.
1537 @param UserInput The user input data.
1539 @retval EFI_SUCESSS This function always return successfully for now.
1544 IN USER_INPUT
*UserInput
1548 FORM_BROWSER_STATEMENT
*Statement
;
1550 Status
= EFI_SUCCESS
;
1554 // When Exit from FormDisplay function, one of the below two cases must be true.
1556 ASSERT (UserInput
->Action
!= 0 || UserInput
->SelectedStatement
!= NULL
);
1559 // Remove the last highligh question id, this id will update when show next form.
1561 gCurrentSelection
->QuestionId
= 0;
1562 if (UserInput
->SelectedStatement
!= NULL
){
1563 Statement
= GetBrowserStatement(UserInput
->SelectedStatement
);
1564 ASSERT (Statement
!= NULL
);
1567 // This question is the current user select one,record it and later
1568 // show it as the highlight question.
1570 gCurrentSelection
->CurrentMenu
->QuestionId
= Statement
->QuestionId
;
1572 // For statement like text, actio, it not has question id.
1573 // So use FakeQuestionId to save the question.
1575 if (gCurrentSelection
->CurrentMenu
->QuestionId
== 0) {
1576 mCurFakeQestId
= Statement
->FakeQuestionId
;
1583 // First process the Action field in USER_INPUT.
1585 if (UserInput
->Action
!= 0) {
1586 Status
= ProcessAction (UserInput
->Action
, UserInput
->DefaultId
);
1587 gCurrentSelection
->Statement
= NULL
;
1589 ASSERT (Statement
!= NULL
);
1590 gCurrentSelection
->Statement
= Statement
;
1591 switch (Statement
->Operand
) {
1592 case EFI_IFR_REF_OP
:
1593 Status
= ProcessGotoOpCode(Statement
, gCurrentSelection
);
1596 case EFI_IFR_ACTION_OP
:
1598 // Process the Config string <ConfigResp>
1600 Status
= ProcessQuestionConfig (gCurrentSelection
, Statement
);
1603 case EFI_IFR_RESET_BUTTON_OP
:
1605 // Reset Question to default value specified by DefaultId
1607 Status
= ExtractDefault (gCurrentSelection
->FormSet
, NULL
, Statement
->DefaultId
, FormSetLevel
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
1608 UpdateStatementStatus (gCurrentSelection
->FormSet
, NULL
, FormSetLevel
);
1612 switch (Statement
->Operand
) {
1613 case EFI_IFR_STRING_OP
:
1614 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1615 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1616 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1617 FreePool (UserInput
->InputValue
.Buffer
);
1620 case EFI_IFR_PASSWORD_OP
:
1621 if (UserInput
->InputValue
.Buffer
== NULL
) {
1623 // User not input new password, just return.
1628 DeleteString(Statement
->HiiValue
.Value
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
1629 Statement
->HiiValue
.Value
.string
= UserInput
->InputValue
.Value
.string
;
1630 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1631 ZeroMem (UserInput
->InputValue
.Buffer
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1632 FreePool (UserInput
->InputValue
.Buffer
);
1634 // Two password match, send it to Configuration Driver
1636 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
1637 PasswordCheck (NULL
, UserInput
->SelectedStatement
, (CHAR16
*) Statement
->BufferValue
);
1639 // Clean the value after saved it.
1641 ZeroMem (Statement
->BufferValue
, (UINTN
) UserInput
->InputValue
.BufferLen
);
1642 HiiSetString (gCurrentSelection
->FormSet
->HiiHandle
, Statement
->HiiValue
.Value
.string
, (CHAR16
*)Statement
->BufferValue
, NULL
);
1644 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithHiiDriver
);
1648 case EFI_IFR_ORDERED_LIST_OP
:
1649 CopyMem (Statement
->BufferValue
, UserInput
->InputValue
.Buffer
, UserInput
->InputValue
.BufferLen
);
1653 CopyMem (&Statement
->HiiValue
, &UserInput
->InputValue
, sizeof (EFI_HII_VALUE
));
1665 Display form and wait for user to select one menu option, then return it.
1667 @retval EFI_SUCESSS This function always return successfully for now.
1676 USER_INPUT UserInput
;
1677 FORM_ENTRY_INFO
*CurrentMenu
;
1679 ZeroMem (&UserInput
, sizeof (USER_INPUT
));
1682 // Update the menu history data.
1684 CurrentMenu
= UiFindMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
, gCurrentSelection
->FormId
);
1685 if (CurrentMenu
== NULL
) {
1687 // Current menu not found, add it to the menu tree
1689 CurrentMenu
= UiAddMenuList (gCurrentSelection
->Handle
, &gCurrentSelection
->FormSetGuid
,
1690 gCurrentSelection
->FormId
, gCurrentSelection
->QuestionId
);
1691 ASSERT (CurrentMenu
!= NULL
);
1695 // Back up the form view history data for this form.
1697 UiCopyMenuList(&gCurrentSelection
->Form
->FormViewListHead
, &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
1699 gCurrentSelection
->CurrentMenu
= CurrentMenu
;
1701 if (gCurrentSelection
->QuestionId
== 0) {
1703 // Highlight not specified, fetch it from cached menu
1705 gCurrentSelection
->QuestionId
= CurrentMenu
->QuestionId
;
1708 Status
= EvaluateFormExpressions (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
);
1709 if (EFI_ERROR (Status
)) {
1713 UpdateDisplayFormData ();
1715 ASSERT (gDisplayFormData
.BrowserStatus
== BROWSER_SUCCESS
);
1716 Status
= mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInput
);
1717 if (EFI_ERROR (Status
)) {
1718 FreeDisplayFormData();
1722 CheckConfigAccess(gCurrentSelection
->FormSet
);
1724 Status
= ProcessUserInput (&UserInput
);
1725 FreeDisplayFormData();
1730 Functions which are registered to receive notification of
1731 database events have this prototype. The actual event is encoded
1732 in NotifyType. The following table describes how PackageType,
1733 PackageGuid, Handle, and Package are used for each of the
1736 @param PackageType Package type of the notification.
1738 @param PackageGuid If PackageType is
1739 EFI_HII_PACKAGE_TYPE_GUID, then this is
1740 the pointer to the GUID from the Guid
1741 field of EFI_HII_PACKAGE_GUID_HEADER.
1742 Otherwise, it must be NULL.
1744 @param Package Points to the package referred to by the
1745 notification Handle The handle of the package
1746 list which contains the specified package.
1748 @param Handle The HII handle.
1750 @param NotifyType The type of change concerning the
1752 EFI_HII_DATABASE_NOTIFY_TYPE.
1758 IN UINT8 PackageType
,
1759 IN CONST EFI_GUID
*PackageGuid
,
1760 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
1761 IN EFI_HII_HANDLE Handle
,
1762 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
1765 mHiiPackageListUpdated
= TRUE
;
1766 mDynamicFormUpdated
= TRUE
;
1772 Update the NV flag info for this form set.
1774 @param FormSet FormSet data structure.
1778 IsNvUpdateRequiredForFormSet (
1779 IN FORM_BROWSER_FORMSET
*FormSet
1783 FORM_BROWSER_FORM
*Form
;
1787 // Not finished question initialization, return FALSE.
1789 if (!FormSet
->QuestionInited
) {
1795 Link
= GetFirstNode (&FormSet
->FormListHead
);
1796 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1797 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1799 RetVal
= IsNvUpdateRequiredForForm(Form
);
1804 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1811 Update the NvUpdateRequired flag for a form.
1813 @param Form Form data structure.
1817 IsNvUpdateRequiredForForm (
1818 IN FORM_BROWSER_FORM
*Form
1822 FORM_BROWSER_STATEMENT
*Statement
;
1824 Link
= GetFirstNode (&Form
->StatementListHead
);
1825 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1826 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1828 if (Statement
->ValueChanged
) {
1832 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1839 Find menu which will show next time.
1841 @param Selection On input, Selection tell setup browser the information
1842 about the Selection, form and formset to be displayed.
1843 On output, Selection return the screen item that is selected
1845 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1846 else, we need to exit current formset.
1848 @retval TRUE Exit current form.
1849 @retval FALSE User press ESC and keep in current form.
1853 IN OUT UI_MENU_SELECTION
*Selection
,
1854 IN BROWSER_SETTING_SCOPE SettingLevel
1857 FORM_ENTRY_INFO
*CurrentMenu
;
1858 FORM_ENTRY_INFO
*ParentMenu
;
1859 BROWSER_SETTING_SCOPE Scope
;
1861 CurrentMenu
= Selection
->CurrentMenu
;
1862 Scope
= FormSetLevel
;
1864 ParentMenu
= UiFindParentMenu(CurrentMenu
, SettingLevel
);
1865 while (ParentMenu
!= NULL
&& !ValidateHiiHandle(ParentMenu
->HiiHandle
)) {
1866 ParentMenu
= UiFindParentMenu(ParentMenu
, SettingLevel
);
1869 if (ParentMenu
!= NULL
) {
1870 if (CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
1873 Scope
= FormSetLevel
;
1878 // Form Level Check whether the data is changed.
1880 if ((gBrowserSettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Selection
->Form
)) ||
1881 (gBrowserSettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet(Selection
->FormSet
) && Scope
== FormSetLevel
)) {
1882 if (!ProcessChangedData(Selection
, gBrowserSettingScope
)) {
1887 if (ParentMenu
!= NULL
) {
1889 // ParentMenu is found. Then, go to it.
1891 if (Scope
== FormLevel
) {
1892 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
1894 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
1895 CopyMem (&Selection
->FormSetGuid
, &ParentMenu
->FormSetGuid
, sizeof (EFI_GUID
));
1896 Selection
->Handle
= ParentMenu
->HiiHandle
;
1899 Selection
->Statement
= NULL
;
1901 Selection
->FormId
= ParentMenu
->FormId
;
1902 Selection
->QuestionId
= ParentMenu
->QuestionId
;
1905 // Clear highlight record for this menu
1907 CurrentMenu
->QuestionId
= 0;
1912 // Current in root page, exit the SendForm
1914 Selection
->Action
= UI_ACTION_EXIT
;
1920 Reconnect the controller.
1922 @param DriverHandle The controller handle which need to be reconnect.
1924 @retval TRUE do the reconnect behavior success.
1925 @retval FALSE do the reconnect behavior failed.
1929 ReconnectController (
1930 IN EFI_HANDLE DriverHandle
1935 Status
= gBS
->DisconnectController(DriverHandle
, NULL
, NULL
);
1936 if (!EFI_ERROR (Status
)) {
1937 Status
= gBS
->ConnectController(DriverHandle
, NULL
, NULL
, TRUE
);
1940 return Status
== EFI_SUCCESS
;
1944 Call the call back function for the question and process the return action.
1946 @param Selection On input, Selection tell setup browser the information
1947 about the Selection, form and formset to be displayed.
1948 On output, Selection return the screen item that is selected
1950 @param FormSet The formset this question belong to.
1951 @param Form The form this question belong to.
1952 @param Question The Question which need to call.
1953 @param Action The action request.
1954 @param SkipSaveOrDiscard Whether skip save or discard action.
1956 @retval EFI_SUCCESS The call back function executes successfully.
1957 @return Other value if the call back function failed to execute.
1960 ProcessCallBackFunction (
1961 IN OUT UI_MENU_SELECTION
*Selection
,
1962 IN FORM_BROWSER_FORMSET
*FormSet
,
1963 IN FORM_BROWSER_FORM
*Form
,
1964 IN FORM_BROWSER_STATEMENT
*Question
,
1965 IN EFI_BROWSER_ACTION Action
,
1966 IN BOOLEAN SkipSaveOrDiscard
1970 EFI_STATUS InternalStatus
;
1971 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1972 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
1973 EFI_HII_VALUE
*HiiValue
;
1974 EFI_IFR_TYPE_VALUE
*TypeValue
;
1975 FORM_BROWSER_STATEMENT
*Statement
;
1976 BOOLEAN SubmitFormIsRequired
;
1977 BOOLEAN DiscardFormIsRequired
;
1980 BROWSER_SETTING_SCOPE SettingLevel
;
1981 EFI_IFR_TYPE_VALUE BackUpValue
;
1982 UINT8
*BackUpBuffer
;
1985 ConfigAccess
= FormSet
->ConfigAccess
;
1986 SubmitFormIsRequired
= FALSE
;
1987 SettingLevel
= FormSetLevel
;
1988 DiscardFormIsRequired
= FALSE
;
1990 Status
= EFI_SUCCESS
;
1991 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1992 BackUpBuffer
= NULL
;
1994 if (ConfigAccess
== NULL
) {
1998 Link
= GetFirstNode (&Form
->StatementListHead
);
1999 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2000 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2001 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2004 // if Question != NULL, only process the question. Else, process all question in this form.
2006 if ((Question
!= NULL
) && (Statement
!= Question
)) {
2010 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2015 // Check whether Statement is disabled.
2017 if (Statement
->Expression
!= NULL
) {
2018 if (EvaluateExpressionList(Statement
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
2023 HiiValue
= &Statement
->HiiValue
;
2024 TypeValue
= &HiiValue
->Value
;
2025 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2027 // For OrderedList, passing in the value buffer to Callback()
2029 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2033 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2035 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2036 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2037 BackUpBuffer
= AllocateCopyPool(Statement
->StorageWidth
, Statement
->BufferValue
);
2038 ASSERT (BackUpBuffer
!= NULL
);
2040 CopyMem (&BackUpValue
, &HiiValue
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2044 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2045 Status
= ConfigAccess
->Callback (
2048 Statement
->QuestionId
,
2053 if (!EFI_ERROR (Status
)) {
2055 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2057 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2058 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2059 ASSERT (NewString
!= NULL
);
2061 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2062 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2063 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2064 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2066 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2068 FreePool (NewString
);
2072 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2075 case EFI_BROWSER_ACTION_CHANGED
:
2076 switch (ActionRequest
) {
2077 case EFI_BROWSER_ACTION_REQUEST_RESET
:
2078 DiscardFormIsRequired
= TRUE
;
2079 gResetRequiredFormLevel
= TRUE
;
2080 gResetRequiredSystemLevel
= TRUE
;
2084 case EFI_BROWSER_ACTION_REQUEST_SUBMIT
:
2085 SubmitFormIsRequired
= TRUE
;
2089 case EFI_BROWSER_ACTION_REQUEST_EXIT
:
2090 DiscardFormIsRequired
= TRUE
;
2094 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
:
2095 SubmitFormIsRequired
= TRUE
;
2096 SettingLevel
= FormLevel
;
2100 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
:
2101 DiscardFormIsRequired
= TRUE
;
2102 SettingLevel
= FormLevel
;
2106 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
:
2107 SubmitFormIsRequired
= TRUE
;
2108 SettingLevel
= FormLevel
;
2111 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
:
2112 DiscardFormIsRequired
= TRUE
;
2113 SettingLevel
= FormLevel
;
2116 case EFI_BROWSER_ACTION_REQUEST_RECONNECT
:
2117 gCallbackReconnect
= TRUE
;
2125 case EFI_BROWSER_ACTION_CHANGING
:
2127 // Do the question validation.
2129 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2130 if (!EFI_ERROR (Status
)) {
2132 //check whether the question value changed compared with edit buffer before updating edit buffer
2133 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2135 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2137 // According the spec, return value from call back of "changing" and
2138 // "retrieve" should update to the question's temp buffer.
2140 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2144 case EFI_BROWSER_ACTION_RETRIEVE
:
2146 // According the spec, return value from call back of "changing" and
2147 // "retrieve" should update to the question's temp buffer.
2149 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2157 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,
2158 // then the browser will use the value passed to Callback() and ignore the
2159 // value returned by Callback().
2161 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
== EFI_UNSUPPORTED
) {
2162 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2163 CopyMem (Statement
->BufferValue
, BackUpBuffer
, Statement
->StorageWidth
);
2165 CopyMem (&HiiValue
->Value
, &BackUpValue
, sizeof (EFI_IFR_TYPE_VALUE
));
2169 // Do the question validation.
2171 InternalStatus
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2172 if (!EFI_ERROR (InternalStatus
)) {
2174 //check whether the question value changed compared with edit buffer before updating edit buffer
2175 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function
2177 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2178 SetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2183 // According the spec, return fail from call back of "changing" and
2184 // "retrieve", should restore the question's value.
2186 if (Action
== EFI_BROWSER_ACTION_CHANGING
&& Status
!= EFI_UNSUPPORTED
) {
2187 if (Statement
->Storage
!= NULL
) {
2188 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2189 } else if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) {
2190 ProcessCallBackFunction (Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2194 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2195 GetQuestionValue(FormSet
, Form
, Statement
, GetSetValueWithEditBuffer
);
2198 if (Status
== EFI_UNSUPPORTED
) {
2200 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2202 Status
= EFI_SUCCESS
;
2206 if (BackUpBuffer
!= NULL
) {
2207 FreePool (BackUpBuffer
);
2211 // If Question != NULL, means just process one question
2212 // and if code reach here means this question has finished
2213 // processing, so just break.
2215 if (Question
!= NULL
) {
2220 if (gCallbackReconnect
&& (EFI_BROWSER_ACTION_CHANGED
== Action
)) {
2222 // Confirm changes with user first.
2224 if (IsNvUpdateRequiredForFormSet(FormSet
)) {
2225 if (BROWSER_ACTION_DISCARD
== PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES
, NULL
, NULL
, NULL
)) {
2226 gCallbackReconnect
= FALSE
;
2227 DiscardFormIsRequired
= TRUE
;
2229 SubmitFormIsRequired
= TRUE
;
2232 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED
, NULL
, NULL
, NULL
);
2236 // Exit current formset before do the reconnect.
2239 SettingLevel
= FormSetLevel
;
2242 if (SubmitFormIsRequired
&& !SkipSaveOrDiscard
) {
2243 SubmitForm (FormSet
, Form
, SettingLevel
);
2246 if (DiscardFormIsRequired
&& !SkipSaveOrDiscard
) {
2247 DiscardForm (FormSet
, Form
, SettingLevel
);
2251 FindNextMenu (Selection
, SettingLevel
);
2258 Call the retrieve type call back function for one question to get the initialize data.
2260 This function only used when in the initialize stage, because in this stage, the
2261 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.
2263 @param ConfigAccess The config access protocol produced by the hii driver.
2264 @param Statement The Question which need to call.
2265 @param FormSet The formset this question belong to.
2267 @retval EFI_SUCCESS The call back function executes successfully.
2268 @return Other value if the call back function failed to execute.
2271 ProcessRetrieveForQuestion (
2272 IN EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
,
2273 IN FORM_BROWSER_STATEMENT
*Statement
,
2274 IN FORM_BROWSER_FORMSET
*FormSet
2278 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2279 EFI_HII_VALUE
*HiiValue
;
2280 EFI_IFR_TYPE_VALUE
*TypeValue
;
2283 Status
= EFI_SUCCESS
;
2284 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2286 if (((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) || ConfigAccess
== NULL
) {
2287 return EFI_UNSUPPORTED
;
2290 HiiValue
= &Statement
->HiiValue
;
2291 TypeValue
= &HiiValue
->Value
;
2292 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
2294 // For OrderedList, passing in the value buffer to Callback()
2296 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Statement
->BufferValue
;
2299 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2300 Status
= ConfigAccess
->Callback (
2302 EFI_BROWSER_ACTION_RETRIEVE
,
2303 Statement
->QuestionId
,
2308 if (!EFI_ERROR (Status
) && HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2309 NewString
= GetToken (Statement
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
2310 ASSERT (NewString
!= NULL
);
2312 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
);
2313 if (StrLen (NewString
) * sizeof (CHAR16
) <= Statement
->StorageWidth
) {
2314 ZeroMem (Statement
->BufferValue
, Statement
->StorageWidth
);
2315 CopyMem (Statement
->BufferValue
, NewString
, StrSize (NewString
));
2317 CopyMem (Statement
->BufferValue
, NewString
, Statement
->StorageWidth
);
2319 FreePool (NewString
);
2326 The worker function that send the displays to the screen. On output,
2327 the selection made by user is returned.
2329 @param Selection On input, Selection tell setup browser the information
2330 about the Selection, form and formset to be displayed.
2331 On output, Selection return the screen item that is selected
2334 @retval EFI_SUCCESS The page is displayed successfully.
2335 @return Other value if the page failed to be diplayed.
2340 IN OUT UI_MENU_SELECTION
*Selection
2345 EFI_HANDLE NotifyHandle
;
2346 FORM_BROWSER_STATEMENT
*Statement
;
2347 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2349 ConfigAccess
= Selection
->FormSet
->ConfigAccess
;
2352 // Register notify for Form package update
2354 Status
= mHiiDatabase
->RegisterPackageNotify (
2356 EFI_HII_PACKAGE_FORMS
,
2359 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
,
2362 if (EFI_ERROR (Status
)) {
2367 // Initialize current settings of Questions in this FormSet
2369 InitializeCurrentSetting (Selection
->FormSet
);
2372 // Initilize Action field.
2374 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2377 // Clean the mCurFakeQestId value is formset refreshed.
2384 // Reset Status to prevent the next break from returning incorrect error status.
2386 Status
= EFI_SUCCESS
;
2389 // IFR is updated, force to reparse the IFR binary
2390 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and
2391 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.
2393 if (mHiiPackageListUpdated
) {
2394 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2395 mHiiPackageListUpdated
= FALSE
;
2400 // Initialize Selection->Form
2402 if (Selection
->FormId
== 0) {
2404 // Zero FormId indicates display the first Form in a FormSet
2406 Link
= GetFirstNode (&Selection
->FormSet
->FormListHead
);
2408 Selection
->Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2409 Selection
->FormId
= Selection
->Form
->FormId
;
2411 Selection
->Form
= IdToForm (Selection
->FormSet
, Selection
->FormId
);
2414 if (Selection
->Form
== NULL
) {
2416 // No Form to display
2418 Status
= EFI_NOT_FOUND
;
2423 // Check Form is suppressed.
2425 if (Selection
->Form
->SuppressExpression
!= NULL
) {
2426 if (EvaluateExpressionList(Selection
->Form
->SuppressExpression
, TRUE
, Selection
->FormSet
, Selection
->Form
) == ExpressSuppress
) {
2428 // Form is suppressed.
2430 PopupErrorMessage(BROWSER_FORM_SUPPRESS
, NULL
, NULL
, NULL
);
2431 Status
= EFI_NOT_FOUND
;
2437 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
2438 // for each question with callback flag.
2439 // New form may be the first form, or the different form after another form close.
2441 if (((Selection
->Handle
!= mCurrentHiiHandle
) ||
2442 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2443 (Selection
->FormId
!= mCurrentFormId
))) {
2445 // Update Retrieve flag.
2447 mFinishRetrieveCall
= FALSE
;
2450 // Keep current form information
2452 mCurrentHiiHandle
= Selection
->Handle
;
2453 CopyGuid (&mCurrentFormSetGuid
, &Selection
->FormSetGuid
);
2454 mCurrentFormId
= Selection
->FormId
;
2456 if (ConfigAccess
!= NULL
) {
2457 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_OPEN
, FALSE
);
2458 if (EFI_ERROR (Status
)) {
2463 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2465 if (mHiiPackageListUpdated
) {
2466 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2467 mHiiPackageListUpdated
= FALSE
;
2474 // Load Questions' Value for display
2476 Status
= LoadFormSetConfig (Selection
, Selection
->FormSet
);
2477 if (EFI_ERROR (Status
)) {
2481 if (!mFinishRetrieveCall
) {
2483 // Finish call RETRIEVE callback for this form.
2485 mFinishRetrieveCall
= TRUE
;
2487 if (ConfigAccess
!= NULL
) {
2488 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_RETRIEVE
, FALSE
);
2489 if (EFI_ERROR (Status
)) {
2494 // IFR is updated during callback of open form, force to reparse the IFR binary
2496 if (mHiiPackageListUpdated
) {
2497 Selection
->Action
= UI_ACTION_REFRESH_FORMSET
;
2498 mHiiPackageListUpdated
= FALSE
;
2507 Status
= DisplayForm ();
2508 if (EFI_ERROR (Status
)) {
2513 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2515 Statement
= Selection
->Statement
;
2516 if (Statement
!= NULL
) {
2517 if ((ConfigAccess
!= NULL
) &&
2518 ((Statement
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
2519 (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2520 Status
= ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGING
, FALSE
);
2521 if (Statement
->Operand
== EFI_IFR_REF_OP
) {
2523 // Process dynamic update ref opcode.
2525 if (!EFI_ERROR (Status
)) {
2526 Status
= ProcessGotoOpCode(Statement
, Selection
);
2530 // Callback return error status or status return from process goto opcode.
2532 if (EFI_ERROR (Status
)) {
2534 // Cross reference will not be taken, restore all essential field
2536 Selection
->Handle
= mCurrentHiiHandle
;
2537 CopyMem (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
, sizeof (EFI_GUID
));
2538 Selection
->FormId
= mCurrentFormId
;
2539 Selection
->QuestionId
= 0;
2540 Selection
->Action
= UI_ACTION_REFRESH_FORM
;
2545 if (!EFI_ERROR (Status
) &&
2546 (Statement
->Operand
!= EFI_IFR_REF_OP
) &&
2547 ((Statement
->Storage
== NULL
) || (Statement
->Storage
!= NULL
&& Statement
->ValueChanged
))) {
2549 // Only question value has been changed, browser will trig CHANGED callback.
2551 ProcessCallBackFunction(Selection
, Selection
->FormSet
, Selection
->Form
, Statement
, EFI_BROWSER_ACTION_CHANGED
, FALSE
);
2553 //check whether the question value changed compared with buffer value
2554 //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen
2556 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2560 // Do the question validation.
2562 Status
= ValueChangedValidation (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
);
2563 if (!EFI_ERROR (Status
) && (Statement
->Operand
!= EFI_IFR_PASSWORD_OP
)) {
2564 SetQuestionValue (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithEditBuffer
);
2566 // Verify whether question value has checked, update the ValueChanged flag in Question.
2568 IsQuestionValueChanged(gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, Statement
, GetSetValueWithBuffer
);
2573 // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage
2574 // and process question success till here, trig the gResetFlag/gFlagReconnect.
2576 if ((Status
== EFI_SUCCESS
) &&
2577 (Statement
->Storage
== NULL
)) {
2578 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2579 gResetRequiredFormLevel
= TRUE
;
2580 gResetRequiredSystemLevel
= TRUE
;
2583 if ((Statement
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2584 gFlagReconnect
= TRUE
;
2590 // Check whether Exit flag is TRUE.
2592 if (gExitRequired
) {
2593 switch (gBrowserSettingScope
) {
2595 Selection
->Action
= UI_ACTION_EXIT
;
2600 FindNextMenu (Selection
, gBrowserSettingScope
);
2607 gExitRequired
= FALSE
;
2611 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2612 // for each question with callback flag.
2614 if ((ConfigAccess
!= NULL
) &&
2615 ((Selection
->Action
== UI_ACTION_EXIT
) ||
2616 (Selection
->Handle
!= mCurrentHiiHandle
) ||
2617 (!CompareGuid (&Selection
->FormSetGuid
, &mCurrentFormSetGuid
)) ||
2618 (Selection
->FormId
!= mCurrentFormId
))) {
2620 Status
= ProcessCallBackFunction (Selection
, Selection
->FormSet
, Selection
->Form
, NULL
, EFI_BROWSER_ACTION_FORM_CLOSE
, FALSE
);
2621 if (EFI_ERROR (Status
)) {
2625 } while (Selection
->Action
== UI_ACTION_REFRESH_FORM
);
2629 // Reset current form information to the initial setting when error happens or form exit.
2631 if (EFI_ERROR (Status
) || Selection
->Action
== UI_ACTION_EXIT
) {
2632 mCurrentHiiHandle
= NULL
;
2633 CopyGuid (&mCurrentFormSetGuid
, &gZeroGuid
);
2638 // Unregister notify for Form package update
2640 mHiiDatabase
->UnregisterPackageNotify (