]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg/Variable/RuntimeDxe: Fix return status from Reclaim()
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
1 /** @file
2 Utility functions for UI presentation.
3
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
7
8 **/
9
10 #include "Setup.h"
11
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;
23
24 /**
25 Check whether the ConfigAccess protocol is available.
26
27 @param FormSet FormSet of which the ConfigAcces protocol need to be checked.
28
29 @retval EFI_SUCCESS The function executed successfully.
30
31 **/
32 EFI_STATUS
33 CheckConfigAccess(
34 IN FORM_BROWSER_FORMSET *FormSet
35 )
36 {
37 EFI_STATUS Status;
38
39 Status = gBS->HandleProtocol (
40 FormSet->DriverHandle,
41 &gEfiHiiConfigAccessProtocolGuid,
42 (VOID **) &FormSet->ConfigAccess
43 );
44 if (EFI_ERROR (Status)) {
45 //
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.
49 //
50 FormSet->ConfigAccess = NULL;
51 }
52
53 return EFI_SUCCESS;
54 }
55
56 /**
57 Evaluate all expressions in a Form.
58
59 @param FormSet FormSet this Form belongs to.
60 @param Form The Form.
61
62 @retval EFI_SUCCESS The expression evaluated successfuly
63
64 **/
65 EFI_STATUS
66 EvaluateFormExpressions (
67 IN FORM_BROWSER_FORMSET *FormSet,
68 IN FORM_BROWSER_FORM *Form
69 )
70 {
71 EFI_STATUS Status;
72 LIST_ENTRY *Link;
73 FORM_EXPRESSION *Expression;
74
75 Link = GetFirstNode (&Form->ExpressionListHead);
76 while (!IsNull (&Form->ExpressionListHead, Link)) {
77 Expression = FORM_EXPRESSION_FROM_LINK (Link);
78 Link = GetNextNode (&Form->ExpressionListHead, Link);
79
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)) {
85 //
86 // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
87 //
88 continue;
89 }
90
91 Status = EvaluateExpression (FormSet, Form, Expression);
92 if (EFI_ERROR (Status)) {
93 return Status;
94 }
95 }
96
97 return EFI_SUCCESS;
98 }
99
100 /**
101 Base on the opcode buffer info to get the display statement.
102
103 @param OpCode The input opcode buffer for this statement.
104
105 @retval Statement The statement use this opcode buffer.
106
107 **/
108 FORM_DISPLAY_ENGINE_STATEMENT *
109 GetDisplayStatement (
110 IN EFI_IFR_OP_HEADER *OpCode
111 )
112 {
113 FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;
114 LIST_ENTRY *Link;
115
116 Link = GetFirstNode (&gDisplayFormData.StatementListHead);
117 while (!IsNull (&gDisplayFormData.StatementListHead, Link)) {
118 DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
119
120 if (DisplayStatement->OpCode == OpCode) {
121 return DisplayStatement;
122 }
123 Link = GetNextNode (&gDisplayFormData.StatementListHead, Link);
124 }
125
126 return NULL;
127 }
128
129 /**
130 Free the refresh event list.
131
132 **/
133 VOID
134 FreeRefreshEvent (
135 VOID
136 )
137 {
138 LIST_ENTRY *Link;
139 FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
140
141 while (!IsListEmpty (&mRefreshEventList)) {
142 Link = GetFirstNode (&mRefreshEventList);
143 EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link);
144 RemoveEntryList (&EventNode->Link);
145
146 gBS->CloseEvent (EventNode->RefreshEvent);
147
148 FreePool (EventNode);
149 }
150 }
151
152 /**
153 Check whether this statement value is changed. If yes, update the statement value and return TRUE;
154 else return FALSE.
155
156 @param Statement The statement need to check.
157
158 **/
159 VOID
160 UpdateStatement (
161 IN OUT FORM_BROWSER_STATEMENT *Statement
162 )
163 {
164 GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);
165
166 //
167 // Reset FormPackage update flag
168 //
169 mHiiPackageListUpdated = FALSE;
170
171 //
172 // Question value may be changed, need invoke its Callback()
173 //
174 ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);
175
176 if (mHiiPackageListUpdated) {
177 //
178 // Package list is updated, force to reparse IFR binary of target Formset
179 //
180 mHiiPackageListUpdated = FALSE;
181 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;
182 }
183 }
184
185 /**
186 Refresh the question which has refresh guid event attribute.
187
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.
190 **/
191 VOID
192 EFIAPI
193 RefreshEventNotifyForStatement(
194 IN EFI_EVENT Event,
195 IN VOID *Context
196 )
197 {
198 FORM_BROWSER_STATEMENT *Statement;
199
200 Statement = (FORM_BROWSER_STATEMENT *)Context;
201 UpdateStatement(Statement);
202 gBS->SignalEvent (mValueChangedEvent);
203 }
204
205 /**
206 Refresh the questions within this form.
207
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.
210 **/
211 VOID
212 EFIAPI
213 RefreshEventNotifyForForm(
214 IN EFI_EVENT Event,
215 IN VOID *Context
216 )
217 {
218 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;
219
220 gBS->SignalEvent (mValueChangedEvent);
221 }
222
223 /**
224 Create refresh hook event for statement which has refresh event or interval.
225
226 @param Statement The statement need to check.
227
228 **/
229 VOID
230 CreateRefreshEventForStatement (
231 IN FORM_BROWSER_STATEMENT *Statement
232 )
233 {
234 EFI_STATUS Status;
235 EFI_EVENT RefreshEvent;
236 FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
237
238 //
239 // If question has refresh guid, create the notify function.
240 //
241 Status = gBS->CreateEventEx (
242 EVT_NOTIFY_SIGNAL,
243 TPL_CALLBACK,
244 RefreshEventNotifyForStatement,
245 Statement,
246 &Statement->RefreshGuid,
247 &RefreshEvent);
248 ASSERT_EFI_ERROR (Status);
249
250 EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));
251 ASSERT (EventNode != NULL);
252 EventNode->RefreshEvent = RefreshEvent;
253 InsertTailList(&mRefreshEventList, &EventNode->Link);
254 }
255
256 /**
257 Create refresh hook event for form which has refresh event or interval.
258
259 @param Form The form need to check.
260
261 **/
262 VOID
263 CreateRefreshEventForForm (
264 IN FORM_BROWSER_FORM *Form
265 )
266 {
267 EFI_STATUS Status;
268 EFI_EVENT RefreshEvent;
269 FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
270
271 //
272 // If question has refresh guid, create the notify function.
273 //
274 Status = gBS->CreateEventEx (
275 EVT_NOTIFY_SIGNAL,
276 TPL_CALLBACK,
277 RefreshEventNotifyForForm,
278 Form,
279 &Form->RefreshGuid,
280 &RefreshEvent);
281 ASSERT_EFI_ERROR (Status);
282
283 EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));
284 ASSERT (EventNode != NULL);
285 EventNode->RefreshEvent = RefreshEvent;
286 InsertTailList(&mRefreshEventList, &EventNode->Link);
287 }
288
289 /**
290
291 Initialize the Display statement structure data.
292
293 @param DisplayStatement Pointer to the display Statement data strucure.
294 @param Statement The statement need to check.
295 **/
296 VOID
297 InitializeDisplayStatement (
298 IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,
299 IN FORM_BROWSER_STATEMENT *Statement
300 )
301 {
302 LIST_ENTRY *Link;
303 QUESTION_OPTION *Option;
304 DISPLAY_QUESTION_OPTION *DisplayOption;
305 FORM_DISPLAY_ENGINE_STATEMENT *ParentStatement;
306
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);
312
313 if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) {
314 DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT;
315 }
316 if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {
317 DisplayStatement->Attribute |= HII_DISPLAY_READONLY;
318 }
319
320 //
321 // Initilize the option list in statement.
322 //
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))) {
329 continue;
330 }
331
332 DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION));
333 ASSERT (DisplayOption != NULL);
334
335 DisplayOption->ImageId = Option->ImageId;
336 DisplayOption->Signature = DISPLAY_QUESTION_OPTION_SIGNATURE;
337 DisplayOption->OptionOpCode = Option->OpCode;
338 InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link);
339 }
340
341 CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));
342
343 //
344 // Some special op code need an extra buffer to save the data.
345 // Such as string, password, orderedlist...
346 //
347 if (Statement->BufferValue != NULL) {
348 //
349 // Ordered list opcode may not initilized, get default value here.
350 //
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);
353 }
354
355 DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);
356 DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;
357 }
358
359 DisplayStatement->SettingChangedFlag = Statement->ValueChanged;
360
361 //
362 // Get the highlight statement for current form.
363 //
364 if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) ||
365 ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) {
366 gDisplayFormData.HighLightedStatement = DisplayStatement;
367 }
368
369 //
370 // Create the refresh event process function.
371 //
372 if (!IsZeroGuid (&Statement->RefreshGuid)) {
373 CreateRefreshEventForStatement (Statement);
374 }
375
376 //
377 // For RTC type of date/time, set default refresh interval to be 1 second.
378 //
379 if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) {
380 Statement->RefreshInterval = 1;
381 }
382
383 //
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.
386 //
387 if ((!IsZeroGuid (&Statement->RefreshGuid)) || (Statement->RefreshInterval != 0)) {
388 gDisplayFormData.FormRefreshEvent = mValueChangedEvent;
389 }
390
391 //
392 // Save the password check function for later use.
393 //
394 if (Statement->Operand == EFI_IFR_PASSWORD_OP) {
395 DisplayStatement->PasswordCheck = PasswordCheck;
396 }
397
398 //
399 // If this statement is nest in the subtitle, insert to the host statement.
400 // else insert to the form it belongs to.
401 //
402 if (Statement->ParentStatement != NULL) {
403 ParentStatement = GetDisplayStatement(Statement->ParentStatement->OpCode);
404 ASSERT (ParentStatement != NULL);
405 InsertTailList(&ParentStatement->NestStatementList, &DisplayStatement->DisplayLink);
406 } else {
407 InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);
408 }
409 }
410
411 /**
412 Process for the refresh interval statement.
413
414 @param Event The Event need to be process
415 @param Context The context of the event.
416
417 **/
418 VOID
419 EFIAPI
420 RefreshIntervalProcess (
421 IN EFI_EVENT Event,
422 IN VOID *Context
423 )
424 {
425 FORM_BROWSER_STATEMENT *Statement;
426 LIST_ENTRY *Link;
427
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);
432
433 if (Statement->RefreshInterval == 0) {
434 continue;
435 }
436
437 UpdateStatement(Statement);
438 }
439
440 gBS->SignalEvent (mValueChangedEvent);
441 }
442
443 /**
444
445 Make a copy of the global hotkey info.
446
447 **/
448 VOID
449 UpdateHotkeyList (
450 VOID
451 )
452 {
453 BROWSER_HOT_KEY *HotKey;
454 BROWSER_HOT_KEY *CopyKey;
455 LIST_ENTRY *Link;
456
457 Link = GetFirstNode (&gBrowserHotKeyList);
458 while (!IsNull (&gBrowserHotKeyList, Link)) {
459 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
460
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);
467
468 InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);
469
470 Link = GetNextNode (&gBrowserHotKeyList, Link);
471 }
472 }
473
474 /**
475
476 Get the extra question attribute from override question list.
477
478 @param QuestionId The question id for this request question.
479
480 @retval The attribute for this question or NULL if not found this
481 question in the list.
482
483 **/
484 UINT32
485 ProcessQuestionExtraAttr (
486 IN EFI_QUESTION_ID QuestionId
487 )
488 {
489 LIST_ENTRY *Link;
490 QUESTION_ATTRIBUTE_OVERRIDE *QuestionDesc;
491
492 //
493 // Return HII_DISPLAY_NONE if input a invalid question id.
494 //
495 if (QuestionId == 0) {
496 return HII_DISPLAY_NONE;
497 }
498
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);
503
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;
509 }
510 }
511
512 return HII_DISPLAY_NONE;
513 }
514
515 /**
516
517 Enum all statement in current form, find all the statement can be display and
518 add to the display form.
519
520 **/
521 VOID
522 AddStatementToDisplayForm (
523 VOID
524 )
525 {
526 EFI_STATUS Status;
527 LIST_ENTRY *Link;
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;
535
536 MinRefreshInterval = 0;
537 FormEditable = FALSE;
538
539 //
540 // Process the statement outside the form, these statements are not recognized
541 // by browser core.
542 //
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);
547
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;
553
554 InitializeListHead (&DisplayStatement->NestStatementList);
555 InitializeListHead (&DisplayStatement->OptionListHead);
556
557 InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);
558 }
559
560 //
561 // treat formset as statement outside the form,get its opcode.
562 //
563 DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));
564 ASSERT (DisplayStatement != NULL);
565
566 DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;
567 DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;
568 DisplayStatement->OpCode = gCurrentSelection->FormSet->OpCode;
569
570 InitializeListHead (&DisplayStatement->NestStatementList);
571 InitializeListHead (&DisplayStatement->OptionListHead);
572
573 InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);
574
575 //
576 // Process the statement in this form.
577 //
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);
582
583 //
584 // This statement can't be show, skip it.
585 //
586 if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {
587 continue;
588 }
589
590 //
591 // Check the extra attribute.
592 //
593 ExtraAttribute = ProcessQuestionExtraAttr (Statement->QuestionId);
594 if ((ExtraAttribute & HII_DISPLAY_SUPPRESS) != 0) {
595 continue;
596 }
597
598 DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));
599 ASSERT (DisplayStatement != NULL);
600
601 //
602 // Initialize this statement and add it to the display form.
603 //
604 InitializeDisplayStatement(DisplayStatement, Statement);
605
606 //
607 // Set the extra attribute.
608 //
609 DisplayStatement->Attribute |= ExtraAttribute;
610
611 if (Statement->Storage != NULL) {
612 FormEditable = TRUE;
613 }
614
615 //
616 // Get the minimal refresh interval value for later use.
617 //
618 if ((Statement->RefreshInterval != 0) &&
619 (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {
620 MinRefreshInterval = Statement->RefreshInterval;
621 }
622 }
623
624 //
625 // Create the periodic timer for refresh interval statement.
626 //
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);
632
633 EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));
634 ASSERT (EventNode != NULL);
635 EventNode->RefreshEvent = RefreshIntervalEvent;
636 InsertTailList(&mRefreshEventList, &EventNode->Link);
637 }
638
639 //
640 // Create the refresh event process function for Form.
641 //
642 if (!IsZeroGuid (&gCurrentSelection->Form->RefreshGuid)) {
643 CreateRefreshEventForForm (gCurrentSelection->Form);
644 if (gDisplayFormData.FormRefreshEvent == NULL) {
645 gDisplayFormData.FormRefreshEvent = mValueChangedEvent;
646 }
647 }
648
649 //
650 // Update hotkey list field.
651 //
652 if (gBrowserSettingScope == SystemLevel || FormEditable) {
653 UpdateHotkeyList();
654 }
655 }
656
657 /**
658
659 Initialize the SettingChangedFlag variable in the display form.
660
661 **/
662 VOID
663 UpdateDataChangedFlag (
664 VOID
665 )
666 {
667 LIST_ENTRY *Link;
668 FORM_BROWSER_FORMSET *LocalFormSet;
669
670 gDisplayFormData.SettingChangedFlag = FALSE;
671
672 if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {
673 gDisplayFormData.SettingChangedFlag = TRUE;
674 return;
675 }
676
677 //
678 // Base on the system level to check whether need to show the NV flag.
679 //
680 switch (gBrowserSettingScope) {
681 case SystemLevel:
682 //
683 // Check the maintain list to see whether there is any change.
684 //
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;
690 return;
691 }
692 Link = GetNextNode (&gBrowserFormSetList, Link);
693 }
694 break;
695
696 case FormSetLevel:
697 if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {
698 gDisplayFormData.SettingChangedFlag = TRUE;
699 return;
700 }
701 break;
702
703 default:
704 break;
705 }
706 }
707
708 /**
709
710 Initialize the Display form structure data.
711
712 **/
713 VOID
714 InitializeDisplayFormData (
715 VOID
716 )
717 {
718 EFI_STATUS Status;
719
720 gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;
721 gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;
722 gDisplayFormData.ImageId = 0;
723 gDisplayFormData.AnimationId = 0;
724
725 InitializeListHead (&gDisplayFormData.StatementListHead);
726 InitializeListHead (&gDisplayFormData.StatementListOSF);
727 InitializeListHead (&gDisplayFormData.HotKeyListHead);
728
729 Status = gBS->CreateEvent (
730 EVT_NOTIFY_WAIT,
731 TPL_CALLBACK,
732 EfiEventEmptyFunction,
733 NULL,
734 &mValueChangedEvent
735 );
736 ASSERT_EFI_ERROR (Status);
737 }
738
739 /**
740
741 Free the kotkey info saved in form data.
742
743 **/
744 VOID
745 FreeHotkeyList (
746 VOID
747 )
748 {
749 BROWSER_HOT_KEY *HotKey;
750 LIST_ENTRY *Link;
751
752 while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {
753 Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);
754 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
755
756 RemoveEntryList (&HotKey->Link);
757
758 FreePool (HotKey->KeyData);
759 FreePool (HotKey->HelpString);
760 FreePool (HotKey);
761 }
762 }
763
764 /**
765
766 Update the Display form structure data.
767
768 **/
769 VOID
770 UpdateDisplayFormData (
771 VOID
772 )
773 {
774 gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle;
775 gDisplayFormData.FormId = gCurrentSelection->FormId;
776 gDisplayFormData.HiiHandle = gCurrentSelection->Handle;
777 CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);
778
779 gDisplayFormData.Attribute = 0;
780 gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;
781 gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0;
782
783 gDisplayFormData.FormRefreshEvent = NULL;
784 gDisplayFormData.HighLightedStatement = NULL;
785
786 UpdateDataChangedFlag ();
787
788 AddStatementToDisplayForm ();
789 }
790
791 /**
792
793 Free the Display Statement structure data.
794
795 @param StatementList Point to the statement list which need to be free.
796
797 **/
798 VOID
799 FreeStatementData (
800 LIST_ENTRY *StatementList
801 )
802 {
803 LIST_ENTRY *Link;
804 LIST_ENTRY *OptionLink;
805 FORM_DISPLAY_ENGINE_STATEMENT *Statement;
806 DISPLAY_QUESTION_OPTION *Option;
807
808 //
809 // Free Statements/Questions
810 //
811 while (!IsListEmpty (StatementList)) {
812 Link = GetFirstNode (StatementList);
813 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
814
815 //
816 // Free Options List
817 //
818 while (!IsListEmpty (&Statement->OptionListHead)) {
819 OptionLink = GetFirstNode (&Statement->OptionListHead);
820 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);
821 RemoveEntryList (&Option->Link);
822 FreePool (Option);
823 }
824
825 //
826 // Free nest statement List
827 //
828 if (!IsListEmpty (&Statement->NestStatementList)) {
829 FreeStatementData(&Statement->NestStatementList);
830 }
831
832 RemoveEntryList (&Statement->DisplayLink);
833 FreePool (Statement);
834 }
835 }
836
837 /**
838
839 Free the Display form structure data.
840
841 **/
842 VOID
843 FreeDisplayFormData (
844 VOID
845 )
846 {
847 FreeStatementData (&gDisplayFormData.StatementListHead);
848 FreeStatementData (&gDisplayFormData.StatementListOSF);
849
850 FreeRefreshEvent();
851
852 FreeHotkeyList();
853 }
854
855 /**
856
857 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
858
859 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
860
861 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
862
863 **/
864 FORM_BROWSER_STATEMENT *
865 GetBrowserStatement (
866 IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement
867 )
868 {
869 FORM_BROWSER_STATEMENT *Statement;
870 LIST_ENTRY *Link;
871
872 Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);
873 while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {
874 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
875
876 if (Statement->OpCode == DisplayStatement->OpCode) {
877 return Statement;
878 }
879
880 Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);
881 }
882
883 return NULL;
884 }
885
886 /**
887 Update the ValueChanged status for questions in this form.
888
889 @param FormSet FormSet data structure.
890 @param Form Form data structure.
891
892 **/
893 VOID
894 UpdateStatementStatusForForm (
895 IN FORM_BROWSER_FORMSET *FormSet,
896 IN FORM_BROWSER_FORM *Form
897 )
898 {
899 LIST_ENTRY *Link;
900 FORM_BROWSER_STATEMENT *Question;
901
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);
906
907 //
908 // For password opcode, not set the the value changed flag.
909 //
910 if (Question->Operand == EFI_IFR_PASSWORD_OP) {
911 continue;
912 }
913
914 IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);
915 }
916 }
917
918 /**
919 Update the ValueChanged status for questions in this formset.
920
921 @param FormSet FormSet data structure.
922
923 **/
924 VOID
925 UpdateStatementStatusForFormSet (
926 IN FORM_BROWSER_FORMSET *FormSet
927 )
928 {
929 LIST_ENTRY *Link;
930 FORM_BROWSER_FORM *Form;
931
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);
936
937 UpdateStatementStatusForForm (FormSet, Form);
938 }
939 }
940
941 /**
942 Update the ValueChanged status for questions.
943
944 @param FormSet FormSet data structure.
945 @param Form Form data structure.
946 @param SettingScope Setting Scope for Default action.
947
948 **/
949 VOID
950 UpdateStatementStatus (
951 IN FORM_BROWSER_FORMSET *FormSet,
952 IN FORM_BROWSER_FORM *Form,
953 IN BROWSER_SETTING_SCOPE SettingScope
954 )
955 {
956 LIST_ENTRY *Link;
957 FORM_BROWSER_FORMSET *LocalFormSet;
958
959 switch (SettingScope) {
960 case SystemLevel:
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)) {
966 continue;
967 }
968
969 UpdateStatementStatusForFormSet (LocalFormSet);
970 }
971 break;
972
973 case FormSetLevel:
974 UpdateStatementStatusForFormSet (FormSet);
975 break;
976
977 case FormLevel:
978 UpdateStatementStatusForForm (FormSet, Form);
979 break;
980
981 default:
982 break;
983 }
984 }
985
986 /**
987
988 Process the action request in user input.
989
990 @param Action The user input action request info.
991 @param DefaultId The user input default Id info.
992
993 @retval EFI_SUCESSS This function always return successfully for now.
994
995 **/
996 EFI_STATUS
997 ProcessAction (
998 IN UINT32 Action,
999 IN UINT16 DefaultId
1000 )
1001 {
1002 //
1003 // This is caused by use press ESC, and it should not combine with other action type.
1004 //
1005 if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {
1006 FindNextMenu (gCurrentSelection, FormLevel);
1007 return EFI_SUCCESS;
1008 }
1009
1010 //
1011 // Below is normal hotkey trigged action, these action maybe combine with each other.
1012 //
1013 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {
1014 DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
1015 }
1016
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);
1020 }
1021
1022 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {
1023 SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
1024 }
1025
1026 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {
1027 gResetRequiredFormLevel = TRUE;
1028 gResetRequiredSystemLevel = TRUE;
1029 }
1030
1031 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {
1032 //
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.
1036 //
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 ();
1043 }
1044 gCurrentSelection->Action = UI_ACTION_EXIT;
1045 }
1046 }
1047
1048 return EFI_SUCCESS;
1049 }
1050
1051 /**
1052 Check whether the formset guid is in this Hii package list.
1053
1054 @param HiiHandle The HiiHandle for this HII package list.
1055 @param FormSetGuid The formset guid for the request formset.
1056
1057 @retval TRUE Find the formset guid.
1058 @retval FALSE Not found the formset guid.
1059
1060 **/
1061 BOOLEAN
1062 GetFormsetGuidFromHiiHandle (
1063 IN EFI_HII_HANDLE HiiHandle,
1064 IN EFI_GUID *FormSetGuid
1065 )
1066 {
1067 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
1068 UINTN BufferSize;
1069 UINT32 Offset;
1070 UINT32 Offset2;
1071 UINT32 PackageListLength;
1072 EFI_HII_PACKAGE_HEADER PackageHeader;
1073 UINT8 *Package;
1074 UINT8 *OpCodeData;
1075 EFI_STATUS Status;
1076 BOOLEAN FindGuid;
1077
1078 BufferSize = 0;
1079 HiiPackageList = NULL;
1080 FindGuid = FALSE;
1081
1082 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
1083 if (Status == EFI_BUFFER_TOO_SMALL) {
1084 HiiPackageList = AllocatePool (BufferSize);
1085 ASSERT (HiiPackageList != NULL);
1086
1087 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
1088 }
1089 if (EFI_ERROR (Status) || HiiPackageList == NULL) {
1090 return FALSE;
1091 }
1092
1093 //
1094 // Get Form package from this HII package List
1095 //
1096 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
1097 Offset2 = 0;
1098 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
1099
1100 while (Offset < PackageListLength) {
1101 Package = ((UINT8 *) HiiPackageList) + Offset;
1102 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
1103 Offset += PackageHeader.Length;
1104
1105 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
1106 //
1107 // Search FormSet in this Form Package
1108 //
1109 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
1110 while (Offset2 < PackageHeader.Length) {
1111 OpCodeData = Package + Offset2;
1112
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)))){
1115 FindGuid = TRUE;
1116 break;
1117 }
1118 }
1119
1120 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1121 }
1122 }
1123 if (FindGuid) {
1124 break;
1125 }
1126 }
1127
1128 FreePool (HiiPackageList);
1129
1130 return FindGuid;
1131 }
1132
1133 /**
1134 Find HII Handle in the HII database associated with given Device Path.
1135
1136 If DevicePath is NULL, then ASSERT.
1137
1138 @param DevicePath Device Path associated with the HII package list
1139 handle.
1140 @param FormsetGuid The formset guid for this formset.
1141
1142 @retval Handle HII package list Handle associated with the Device
1143 Path.
1144 @retval NULL Hii Package list handle is not found.
1145
1146 **/
1147 EFI_HII_HANDLE
1148 DevicePathToHiiHandle (
1149 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1150 IN EFI_GUID *FormsetGuid
1151 )
1152 {
1153 EFI_STATUS Status;
1154 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
1155 UINTN Index;
1156 EFI_HANDLE Handle;
1157 EFI_HANDLE DriverHandle;
1158 EFI_HII_HANDLE *HiiHandles;
1159 EFI_HII_HANDLE HiiHandle;
1160
1161 ASSERT (DevicePath != NULL);
1162
1163 TmpDevicePath = DevicePath;
1164 //
1165 // Locate Device Path Protocol handle buffer
1166 //
1167 Status = gBS->LocateDevicePath (
1168 &gEfiDevicePathProtocolGuid,
1169 &TmpDevicePath,
1170 &DriverHandle
1171 );
1172 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
1173 return NULL;
1174 }
1175
1176 //
1177 // Retrieve all HII Handles from HII database
1178 //
1179 HiiHandles = HiiGetHiiHandles (NULL);
1180 if (HiiHandles == NULL) {
1181 return NULL;
1182 }
1183
1184 //
1185 // Search Hii Handle by Driver Handle
1186 //
1187 HiiHandle = NULL;
1188 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
1189 Status = mHiiDatabase->GetPackageListHandle (
1190 mHiiDatabase,
1191 HiiHandles[Index],
1192 &Handle
1193 );
1194 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
1195 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {
1196 HiiHandle = HiiHandles[Index];
1197 break;
1198 }
1199
1200 if (HiiHandle != NULL) {
1201 break;
1202 }
1203 }
1204 }
1205
1206 FreePool (HiiHandles);
1207 return HiiHandle;
1208 }
1209
1210 /**
1211 Find HII Handle in the HII database associated with given form set guid.
1212
1213 If FormSetGuid is NULL, then ASSERT.
1214
1215 @param ComparingGuid FormSet Guid associated with the HII package list
1216 handle.
1217
1218 @retval Handle HII package list Handle associated with the Device
1219 Path.
1220 @retval NULL Hii Package list handle is not found.
1221
1222 **/
1223 EFI_HII_HANDLE
1224 FormSetGuidToHiiHandle (
1225 EFI_GUID *ComparingGuid
1226 )
1227 {
1228 EFI_HII_HANDLE *HiiHandles;
1229 EFI_HII_HANDLE HiiHandle;
1230 UINTN Index;
1231
1232 ASSERT (ComparingGuid != NULL);
1233
1234 HiiHandle = NULL;
1235 //
1236 // Get all the Hii handles
1237 //
1238 HiiHandles = HiiGetHiiHandles (NULL);
1239 ASSERT (HiiHandles != NULL);
1240
1241 //
1242 // Search for formset of each class type
1243 //
1244 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
1245 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {
1246 HiiHandle = HiiHandles[Index];
1247 break;
1248 }
1249
1250 if (HiiHandle != NULL) {
1251 break;
1252 }
1253 }
1254
1255 FreePool (HiiHandles);
1256
1257 return HiiHandle;
1258 }
1259
1260 /**
1261 check how to process the changed data in current form or form set.
1262
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
1266 by user.
1267
1268 @param Scope Data save or discard scope, form or formset.
1269
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.
1272 **/
1273 BOOLEAN
1274 ProcessChangedData (
1275 IN OUT UI_MENU_SELECTION *Selection,
1276 IN BROWSER_SETTING_SCOPE Scope
1277 )
1278 {
1279 BOOLEAN RetValue;
1280 EFI_STATUS Status;
1281
1282 RetValue = TRUE;
1283 switch (mFormDisplay->ConfirmDataChange()) {
1284 case BROWSER_ACTION_DISCARD:
1285 DiscardForm (Selection->FormSet, Selection->Form, Scope);
1286 break;
1287
1288 case BROWSER_ACTION_SUBMIT:
1289 Status = SubmitForm (Selection->FormSet, Selection->Form, Scope);
1290 if (EFI_ERROR (Status)) {
1291 RetValue = FALSE;
1292 }
1293 break;
1294
1295 case BROWSER_ACTION_NONE:
1296 RetValue = FALSE;
1297 break;
1298
1299 default:
1300 //
1301 // if Invalid value return, process same as BROWSER_ACTION_NONE.
1302 //
1303 RetValue = FALSE;
1304 break;
1305 }
1306
1307 return RetValue;
1308 }
1309
1310 /**
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.
1313
1314 @param Selection The selection info.
1315
1316 **/
1317 VOID
1318 FindParentFormSet (
1319 IN OUT UI_MENU_SELECTION *Selection
1320 )
1321 {
1322 FORM_ENTRY_INFO *CurrentMenu;
1323 FORM_ENTRY_INFO *ParentMenu;
1324
1325 CurrentMenu = Selection->CurrentMenu;
1326 ParentMenu = UiFindParentMenu(CurrentMenu, FormSetLevel);
1327
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;
1333 } else {
1334 Selection->FormId = CurrentMenu->FormId;
1335 Selection->QuestionId = CurrentMenu->QuestionId;
1336 }
1337
1338 Selection->Statement = NULL;
1339 }
1340
1341 /**
1342 Process the goto op code, update the info in the selection structure.
1343
1344 @param Statement The statement belong to goto op code.
1345 @param Selection The selection info.
1346
1347 @retval EFI_SUCCESS The menu process successfully.
1348 @return Other value if the process failed.
1349 **/
1350 EFI_STATUS
1351 ProcessGotoOpCode (
1352 IN OUT FORM_BROWSER_STATEMENT *Statement,
1353 IN OUT UI_MENU_SELECTION *Selection
1354 )
1355 {
1356 CHAR16 *StringPtr;
1357 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1358 FORM_BROWSER_FORM *RefForm;
1359 EFI_STATUS Status;
1360 EFI_HII_HANDLE HiiHandle;
1361
1362 Status = EFI_SUCCESS;
1363 StringPtr = NULL;
1364 HiiHandle = NULL;
1365
1366 //
1367 // Prepare the device path check, get the device path info first.
1368 //
1369 if (Statement->HiiValue.Value.ref.DevicePath != 0) {
1370 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);
1371 }
1372
1373 //
1374 // Check whether the device path string is a valid string.
1375 //
1376 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {
1377 if (Selection->Form->ModalForm) {
1378 return Status;
1379 }
1380
1381 //
1382 // Goto another Hii Package list
1383 //
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);
1389 }
1390 FreePool (StringPtr);
1391 } else {
1392 //
1393 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
1394 //
1395 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);
1396 FreePool (StringPtr);
1397 return Status;
1398 }
1399
1400 if (HiiHandle != Selection->Handle) {
1401 //
1402 // Goto another Formset, check for uncommitted data
1403 //
1404 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&
1405 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {
1406 if (!ProcessChangedData(Selection, FormSetLevel)) {
1407 return EFI_SUCCESS;
1408 }
1409 }
1410 }
1411
1412 Selection->Action = UI_ACTION_REFRESH_FORMSET;
1413 Selection->Handle = HiiHandle;
1414 if (Selection->Handle == NULL) {
1415 //
1416 // If target Hii Handle not found, exit current formset.
1417 //
1418 FindParentFormSet(Selection);
1419 return EFI_SUCCESS;
1420 }
1421
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) {
1427 return Status;
1428 }
1429 if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {
1430 //
1431 // Goto another Formset, check for uncommitted data
1432 //
1433 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&
1434 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {
1435 if (!ProcessChangedData(Selection, FormSetLevel)) {
1436 return EFI_SUCCESS;
1437 }
1438 }
1439 }
1440
1441 Selection->Action = UI_ACTION_REFRESH_FORMSET;
1442 Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);
1443 if (Selection->Handle == NULL) {
1444 //
1445 // If target Hii Handle not found, exit current formset.
1446 //
1447 FindParentFormSet(Selection);
1448 return EFI_SUCCESS;
1449 }
1450
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) {
1455 //
1456 // Goto another Form, check for uncommitted data
1457 //
1458 if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {
1459 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {
1460 if (!ProcessChangedData (Selection, FormLevel)) {
1461 return EFI_SUCCESS;
1462 }
1463 }
1464 }
1465
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) {
1469 //
1470 // Form is suppressed.
1471 //
1472 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);
1473 return EFI_SUCCESS;
1474 }
1475 }
1476
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;
1481 }
1482
1483 return Status;
1484 }
1485
1486
1487 /**
1488 Process Question Config.
1489
1490 @param Selection The UI menu selection.
1491 @param Question The Question to be peocessed.
1492
1493 @retval EFI_SUCCESS Question Config process success.
1494 @retval Other Question Config process fail.
1495
1496 **/
1497 EFI_STATUS
1498 ProcessQuestionConfig (
1499 IN UI_MENU_SELECTION *Selection,
1500 IN FORM_BROWSER_STATEMENT *Question
1501 )
1502 {
1503 EFI_STATUS Status;
1504 CHAR16 *ConfigResp;
1505 CHAR16 *Progress;
1506
1507 if (Question->QuestionConfig == 0) {
1508 return EFI_SUCCESS;
1509 }
1510
1511 //
1512 // Get <ConfigResp>
1513 //
1514 ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);
1515 if (ConfigResp == NULL) {
1516 return EFI_NOT_FOUND;
1517 } else if (ConfigResp[0] == L'\0') {
1518 return EFI_SUCCESS;
1519 }
1520
1521 //
1522 // Send config to Configuration Driver
1523 //
1524 Status = mHiiConfigRouting->RouteConfig (
1525 mHiiConfigRouting,
1526 ConfigResp,
1527 &Progress
1528 );
1529
1530 return Status;
1531 }
1532
1533 /**
1534
1535 Process the user input data.
1536
1537 @param UserInput The user input data.
1538
1539 @retval EFI_SUCESSS This function always return successfully for now.
1540
1541 **/
1542 EFI_STATUS
1543 ProcessUserInput (
1544 IN USER_INPUT *UserInput
1545 )
1546 {
1547 EFI_STATUS Status;
1548 FORM_BROWSER_STATEMENT *Statement;
1549
1550 Status = EFI_SUCCESS;
1551 Statement = NULL;
1552
1553 //
1554 // When Exit from FormDisplay function, one of the below two cases must be true.
1555 //
1556 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);
1557
1558 //
1559 // Remove the last highligh question id, this id will update when show next form.
1560 //
1561 gCurrentSelection->QuestionId = 0;
1562 if (UserInput->SelectedStatement != NULL){
1563 Statement = GetBrowserStatement(UserInput->SelectedStatement);
1564 ASSERT (Statement != NULL);
1565
1566 //
1567 // This question is the current user select one,record it and later
1568 // show it as the highlight question.
1569 //
1570 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;
1571 //
1572 // For statement like text, actio, it not has question id.
1573 // So use FakeQuestionId to save the question.
1574 //
1575 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {
1576 mCurFakeQestId = Statement->FakeQuestionId;
1577 } else {
1578 mCurFakeQestId = 0;
1579 }
1580 }
1581
1582 //
1583 // First process the Action field in USER_INPUT.
1584 //
1585 if (UserInput->Action != 0) {
1586 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);
1587 gCurrentSelection->Statement = NULL;
1588 } else {
1589 ASSERT (Statement != NULL);
1590 gCurrentSelection->Statement = Statement;
1591 switch (Statement->Operand) {
1592 case EFI_IFR_REF_OP:
1593 Status = ProcessGotoOpCode(Statement, gCurrentSelection);
1594 break;
1595
1596 case EFI_IFR_ACTION_OP:
1597 //
1598 // Process the Config string <ConfigResp>
1599 //
1600 Status = ProcessQuestionConfig (gCurrentSelection, Statement);
1601 break;
1602
1603 case EFI_IFR_RESET_BUTTON_OP:
1604 //
1605 // Reset Question to default value specified by DefaultId
1606 //
1607 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);
1608 UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);
1609 break;
1610
1611 default:
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);
1618 break;
1619
1620 case EFI_IFR_PASSWORD_OP:
1621 if (UserInput->InputValue.Buffer == NULL) {
1622 //
1623 // User not input new password, just return.
1624 //
1625 break;
1626 }
1627
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);
1633 //
1634 // Two password match, send it to Configuration Driver
1635 //
1636 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
1637 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);
1638 //
1639 // Clean the value after saved it.
1640 //
1641 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);
1642 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);
1643 } else {
1644 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);
1645 }
1646 break;
1647
1648 case EFI_IFR_ORDERED_LIST_OP:
1649 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);
1650 break;
1651
1652 default:
1653 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));
1654 break;
1655 }
1656 break;
1657 }
1658 }
1659
1660 return Status;
1661 }
1662
1663 /**
1664
1665 Display form and wait for user to select one menu option, then return it.
1666
1667 @retval EFI_SUCESSS This function always return successfully for now.
1668
1669 **/
1670 EFI_STATUS
1671 DisplayForm (
1672 VOID
1673 )
1674 {
1675 EFI_STATUS Status;
1676 USER_INPUT UserInput;
1677 FORM_ENTRY_INFO *CurrentMenu;
1678
1679 ZeroMem (&UserInput, sizeof (USER_INPUT));
1680
1681 //
1682 // Update the menu history data.
1683 //
1684 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);
1685 if (CurrentMenu == NULL) {
1686 //
1687 // Current menu not found, add it to the menu tree
1688 //
1689 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,
1690 gCurrentSelection->FormId, gCurrentSelection->QuestionId);
1691 ASSERT (CurrentMenu != NULL);
1692 }
1693
1694 //
1695 // Back up the form view history data for this form.
1696 //
1697 UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);
1698
1699 gCurrentSelection->CurrentMenu = CurrentMenu;
1700
1701 if (gCurrentSelection->QuestionId == 0) {
1702 //
1703 // Highlight not specified, fetch it from cached menu
1704 //
1705 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;
1706 }
1707
1708 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);
1709 if (EFI_ERROR (Status)) {
1710 return Status;
1711 }
1712
1713 UpdateDisplayFormData ();
1714
1715 ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);
1716 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);
1717 if (EFI_ERROR (Status)) {
1718 FreeDisplayFormData();
1719 return Status;
1720 }
1721
1722 CheckConfigAccess(gCurrentSelection->FormSet);
1723
1724 Status = ProcessUserInput (&UserInput);
1725 FreeDisplayFormData();
1726 return Status;
1727 }
1728
1729 /**
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
1734 notification types.
1735
1736 @param PackageType Package type of the notification.
1737
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.
1743
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.
1747
1748 @param Handle The HII handle.
1749
1750 @param NotifyType The type of change concerning the
1751 database. See
1752 EFI_HII_DATABASE_NOTIFY_TYPE.
1753
1754 **/
1755 EFI_STATUS
1756 EFIAPI
1757 FormUpdateNotify (
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
1763 )
1764 {
1765 mHiiPackageListUpdated = TRUE;
1766 mDynamicFormUpdated = TRUE;
1767
1768 return EFI_SUCCESS;
1769 }
1770
1771 /**
1772 Update the NV flag info for this form set.
1773
1774 @param FormSet FormSet data structure.
1775
1776 **/
1777 BOOLEAN
1778 IsNvUpdateRequiredForFormSet (
1779 IN FORM_BROWSER_FORMSET *FormSet
1780 )
1781 {
1782 LIST_ENTRY *Link;
1783 FORM_BROWSER_FORM *Form;
1784 BOOLEAN RetVal;
1785
1786 //
1787 // Not finished question initialization, return FALSE.
1788 //
1789 if (!FormSet->QuestionInited) {
1790 return FALSE;
1791 }
1792
1793 RetVal = FALSE;
1794
1795 Link = GetFirstNode (&FormSet->FormListHead);
1796 while (!IsNull (&FormSet->FormListHead, Link)) {
1797 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
1798
1799 RetVal = IsNvUpdateRequiredForForm(Form);
1800 if (RetVal) {
1801 break;
1802 }
1803
1804 Link = GetNextNode (&FormSet->FormListHead, Link);
1805 }
1806
1807 return RetVal;
1808 }
1809
1810 /**
1811 Update the NvUpdateRequired flag for a form.
1812
1813 @param Form Form data structure.
1814
1815 **/
1816 BOOLEAN
1817 IsNvUpdateRequiredForForm (
1818 IN FORM_BROWSER_FORM *Form
1819 )
1820 {
1821 LIST_ENTRY *Link;
1822 FORM_BROWSER_STATEMENT *Statement;
1823
1824 Link = GetFirstNode (&Form->StatementListHead);
1825 while (!IsNull (&Form->StatementListHead, Link)) {
1826 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1827
1828 if (Statement->ValueChanged) {
1829 return TRUE;
1830 }
1831
1832 Link = GetNextNode (&Form->StatementListHead, Link);
1833 }
1834
1835 return FALSE;
1836 }
1837
1838 /**
1839 Find menu which will show next time.
1840
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
1844 by user.
1845 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
1846 else, we need to exit current formset.
1847
1848 @retval TRUE Exit current form.
1849 @retval FALSE User press ESC and keep in current form.
1850 **/
1851 BOOLEAN
1852 FindNextMenu (
1853 IN OUT UI_MENU_SELECTION *Selection,
1854 IN BROWSER_SETTING_SCOPE SettingLevel
1855 )
1856 {
1857 FORM_ENTRY_INFO *CurrentMenu;
1858 FORM_ENTRY_INFO *ParentMenu;
1859 BROWSER_SETTING_SCOPE Scope;
1860
1861 CurrentMenu = Selection->CurrentMenu;
1862 Scope = FormSetLevel;
1863
1864 ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);
1865 while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {
1866 ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);
1867 }
1868
1869 if (ParentMenu != NULL) {
1870 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
1871 Scope = FormLevel;
1872 } else {
1873 Scope = FormSetLevel;
1874 }
1875 }
1876
1877 //
1878 // Form Level Check whether the data is changed.
1879 //
1880 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||
1881 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {
1882 if (!ProcessChangedData(Selection, gBrowserSettingScope)) {
1883 return FALSE;
1884 }
1885 }
1886
1887 if (ParentMenu != NULL) {
1888 //
1889 // ParentMenu is found. Then, go to it.
1890 //
1891 if (Scope == FormLevel) {
1892 Selection->Action = UI_ACTION_REFRESH_FORM;
1893 } else {
1894 Selection->Action = UI_ACTION_REFRESH_FORMSET;
1895 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));
1896 Selection->Handle = ParentMenu->HiiHandle;
1897 }
1898
1899 Selection->Statement = NULL;
1900
1901 Selection->FormId = ParentMenu->FormId;
1902 Selection->QuestionId = ParentMenu->QuestionId;
1903
1904 //
1905 // Clear highlight record for this menu
1906 //
1907 CurrentMenu->QuestionId = 0;
1908 return FALSE;
1909 }
1910
1911 //
1912 // Current in root page, exit the SendForm
1913 //
1914 Selection->Action = UI_ACTION_EXIT;
1915
1916 return TRUE;
1917 }
1918
1919 /**
1920 Reconnect the controller.
1921
1922 @param DriverHandle The controller handle which need to be reconnect.
1923
1924 @retval TRUE do the reconnect behavior success.
1925 @retval FALSE do the reconnect behavior failed.
1926
1927 **/
1928 BOOLEAN
1929 ReconnectController (
1930 IN EFI_HANDLE DriverHandle
1931 )
1932 {
1933 EFI_STATUS Status;
1934
1935 Status = gBS->DisconnectController(DriverHandle, NULL, NULL);
1936 if (!EFI_ERROR (Status)) {
1937 Status = gBS->ConnectController(DriverHandle, NULL, NULL, TRUE);
1938 }
1939
1940 return Status == EFI_SUCCESS;
1941 }
1942
1943 /**
1944 Call the call back function for the question and process the return action.
1945
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
1949 by user.
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.
1955
1956 @retval EFI_SUCCESS The call back function executes successfully.
1957 @return Other value if the call back function failed to execute.
1958 **/
1959 EFI_STATUS
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
1967 )
1968 {
1969 EFI_STATUS Status;
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;
1978 BOOLEAN NeedExit;
1979 LIST_ENTRY *Link;
1980 BROWSER_SETTING_SCOPE SettingLevel;
1981 EFI_IFR_TYPE_VALUE BackUpValue;
1982 UINT8 *BackUpBuffer;
1983 CHAR16 *NewString;
1984
1985 ConfigAccess = FormSet->ConfigAccess;
1986 SubmitFormIsRequired = FALSE;
1987 SettingLevel = FormSetLevel;
1988 DiscardFormIsRequired = FALSE;
1989 NeedExit = FALSE;
1990 Status = EFI_SUCCESS;
1991 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
1992 BackUpBuffer = NULL;
1993
1994 if (ConfigAccess == NULL) {
1995 return EFI_SUCCESS;
1996 }
1997
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);
2002
2003 //
2004 // if Question != NULL, only process the question. Else, process all question in this form.
2005 //
2006 if ((Question != NULL) && (Statement != Question)) {
2007 continue;
2008 }
2009
2010 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {
2011 continue;
2012 }
2013
2014 //
2015 // Check whether Statement is disabled.
2016 //
2017 if (Statement->Expression != NULL) {
2018 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {
2019 continue;
2020 }
2021 }
2022
2023 HiiValue = &Statement->HiiValue;
2024 TypeValue = &HiiValue->Value;
2025 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
2026 //
2027 // For OrderedList, passing in the value buffer to Callback()
2028 //
2029 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;
2030 }
2031
2032 //
2033 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.
2034 //
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);
2039 } else {
2040 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
2041 }
2042 }
2043
2044 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
2045 Status = ConfigAccess->Callback (
2046 ConfigAccess,
2047 Action,
2048 Statement->QuestionId,
2049 HiiValue->Type,
2050 TypeValue,
2051 &ActionRequest
2052 );
2053 if (!EFI_ERROR (Status)) {
2054 //
2055 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue
2056 //
2057 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
2058 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);
2059 ASSERT (NewString != NULL);
2060
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));
2065 } else {
2066 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);
2067 }
2068 FreePool (NewString);
2069 }
2070
2071 //
2072 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.
2073 //
2074 switch (Action) {
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;
2081 NeedExit = TRUE;
2082 break;
2083
2084 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
2085 SubmitFormIsRequired = TRUE;
2086 NeedExit = TRUE;
2087 break;
2088
2089 case EFI_BROWSER_ACTION_REQUEST_EXIT:
2090 DiscardFormIsRequired = TRUE;
2091 NeedExit = TRUE;
2092 break;
2093
2094 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:
2095 SubmitFormIsRequired = TRUE;
2096 SettingLevel = FormLevel;
2097 NeedExit = TRUE;
2098 break;
2099
2100 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:
2101 DiscardFormIsRequired = TRUE;
2102 SettingLevel = FormLevel;
2103 NeedExit = TRUE;
2104 break;
2105
2106 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:
2107 SubmitFormIsRequired = TRUE;
2108 SettingLevel = FormLevel;
2109 break;
2110
2111 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:
2112 DiscardFormIsRequired = TRUE;
2113 SettingLevel = FormLevel;
2114 break;
2115
2116 case EFI_BROWSER_ACTION_REQUEST_RECONNECT:
2117 gCallbackReconnect = TRUE;
2118 break;
2119
2120 default:
2121 break;
2122 }
2123 break;
2124
2125 case EFI_BROWSER_ACTION_CHANGING:
2126 //
2127 // Do the question validation.
2128 //
2129 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);
2130 if (!EFI_ERROR (Status)) {
2131 //
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
2134 //
2135 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);
2136 //
2137 // According the spec, return value from call back of "changing" and
2138 // "retrieve" should update to the question's temp buffer.
2139 //
2140 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
2141 }
2142 break;
2143
2144 case EFI_BROWSER_ACTION_RETRIEVE:
2145 //
2146 // According the spec, return value from call back of "changing" and
2147 // "retrieve" should update to the question's temp buffer.
2148 //
2149 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
2150 break;
2151
2152 default:
2153 break;
2154 }
2155 } else {
2156 //
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().
2160 //
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);
2164 } else {
2165 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));
2166 }
2167
2168 //
2169 // Do the question validation.
2170 //
2171 InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);
2172 if (!EFI_ERROR (InternalStatus)) {
2173 //
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
2176 //
2177 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);
2178 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
2179 }
2180 }
2181
2182 //
2183 // According the spec, return fail from call back of "changing" and
2184 // "retrieve", should restore the question's value.
2185 //
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);
2191 }
2192 }
2193
2194 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
2195 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
2196 }
2197
2198 if (Status == EFI_UNSUPPORTED) {
2199 //
2200 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
2201 //
2202 Status = EFI_SUCCESS;
2203 }
2204 }
2205
2206 if (BackUpBuffer != NULL) {
2207 FreePool (BackUpBuffer);
2208 }
2209
2210 //
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.
2214 //
2215 if (Question != NULL) {
2216 break;
2217 }
2218 }
2219
2220 if (gCallbackReconnect && (EFI_BROWSER_ACTION_CHANGED == Action)) {
2221 //
2222 // Confirm changes with user first.
2223 //
2224 if (IsNvUpdateRequiredForFormSet(FormSet)) {
2225 if (BROWSER_ACTION_DISCARD == PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES, NULL, NULL, NULL)) {
2226 gCallbackReconnect = FALSE;
2227 DiscardFormIsRequired = TRUE;
2228 } else {
2229 SubmitFormIsRequired = TRUE;
2230 }
2231 } else {
2232 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED, NULL, NULL, NULL);
2233 }
2234
2235 //
2236 // Exit current formset before do the reconnect.
2237 //
2238 NeedExit = TRUE;
2239 SettingLevel = FormSetLevel;
2240 }
2241
2242 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {
2243 SubmitForm (FormSet, Form, SettingLevel);
2244 }
2245
2246 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {
2247 DiscardForm (FormSet, Form, SettingLevel);
2248 }
2249
2250 if (NeedExit) {
2251 FindNextMenu (Selection, SettingLevel);
2252 }
2253
2254 return Status;
2255 }
2256
2257 /**
2258 Call the retrieve type call back function for one question to get the initialize data.
2259
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.
2262
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.
2266
2267 @retval EFI_SUCCESS The call back function executes successfully.
2268 @return Other value if the call back function failed to execute.
2269 **/
2270 EFI_STATUS
2271 ProcessRetrieveForQuestion (
2272 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,
2273 IN FORM_BROWSER_STATEMENT *Statement,
2274 IN FORM_BROWSER_FORMSET *FormSet
2275 )
2276 {
2277 EFI_STATUS Status;
2278 EFI_BROWSER_ACTION_REQUEST ActionRequest;
2279 EFI_HII_VALUE *HiiValue;
2280 EFI_IFR_TYPE_VALUE *TypeValue;
2281 CHAR16 *NewString;
2282
2283 Status = EFI_SUCCESS;
2284 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
2285
2286 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {
2287 return EFI_UNSUPPORTED;
2288 }
2289
2290 HiiValue = &Statement->HiiValue;
2291 TypeValue = &HiiValue->Value;
2292 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
2293 //
2294 // For OrderedList, passing in the value buffer to Callback()
2295 //
2296 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;
2297 }
2298
2299 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
2300 Status = ConfigAccess->Callback (
2301 ConfigAccess,
2302 EFI_BROWSER_ACTION_RETRIEVE,
2303 Statement->QuestionId,
2304 HiiValue->Type,
2305 TypeValue,
2306 &ActionRequest
2307 );
2308 if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {
2309 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);
2310 ASSERT (NewString != NULL);
2311
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));
2316 } else {
2317 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);
2318 }
2319 FreePool (NewString);
2320 }
2321
2322 return Status;
2323 }
2324
2325 /**
2326 The worker function that send the displays to the screen. On output,
2327 the selection made by user is returned.
2328
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
2332 by user.
2333
2334 @retval EFI_SUCCESS The page is displayed successfully.
2335 @return Other value if the page failed to be diplayed.
2336
2337 **/
2338 EFI_STATUS
2339 SetupBrowser (
2340 IN OUT UI_MENU_SELECTION *Selection
2341 )
2342 {
2343 EFI_STATUS Status;
2344 LIST_ENTRY *Link;
2345 EFI_HANDLE NotifyHandle;
2346 FORM_BROWSER_STATEMENT *Statement;
2347 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2348
2349 ConfigAccess = Selection->FormSet->ConfigAccess;
2350
2351 //
2352 // Register notify for Form package update
2353 //
2354 Status = mHiiDatabase->RegisterPackageNotify (
2355 mHiiDatabase,
2356 EFI_HII_PACKAGE_FORMS,
2357 NULL,
2358 FormUpdateNotify,
2359 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2360 &NotifyHandle
2361 );
2362 if (EFI_ERROR (Status)) {
2363 return Status;
2364 }
2365
2366 //
2367 // Initialize current settings of Questions in this FormSet
2368 //
2369 InitializeCurrentSetting (Selection->FormSet);
2370
2371 //
2372 // Initilize Action field.
2373 //
2374 Selection->Action = UI_ACTION_REFRESH_FORM;
2375
2376 //
2377 // Clean the mCurFakeQestId value is formset refreshed.
2378 //
2379 mCurFakeQestId = 0;
2380
2381 do {
2382
2383 //
2384 // Reset Status to prevent the next break from returning incorrect error status.
2385 //
2386 Status = EFI_SUCCESS;
2387
2388 //
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.
2392 //
2393 if (mHiiPackageListUpdated) {
2394 Selection->Action = UI_ACTION_REFRESH_FORMSET;
2395 mHiiPackageListUpdated = FALSE;
2396 break;
2397 }
2398
2399 //
2400 // Initialize Selection->Form
2401 //
2402 if (Selection->FormId == 0) {
2403 //
2404 // Zero FormId indicates display the first Form in a FormSet
2405 //
2406 Link = GetFirstNode (&Selection->FormSet->FormListHead);
2407
2408 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
2409 Selection->FormId = Selection->Form->FormId;
2410 } else {
2411 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
2412 }
2413
2414 if (Selection->Form == NULL) {
2415 //
2416 // No Form to display
2417 //
2418 Status = EFI_NOT_FOUND;
2419 goto Done;
2420 }
2421
2422 //
2423 // Check Form is suppressed.
2424 //
2425 if (Selection->Form->SuppressExpression != NULL) {
2426 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {
2427 //
2428 // Form is suppressed.
2429 //
2430 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);
2431 Status = EFI_NOT_FOUND;
2432 goto Done;
2433 }
2434 }
2435
2436 //
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.
2440 //
2441 if (((Selection->Handle != mCurrentHiiHandle) ||
2442 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||
2443 (Selection->FormId != mCurrentFormId))) {
2444 //
2445 // Update Retrieve flag.
2446 //
2447 mFinishRetrieveCall = FALSE;
2448
2449 //
2450 // Keep current form information
2451 //
2452 mCurrentHiiHandle = Selection->Handle;
2453 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);
2454 mCurrentFormId = Selection->FormId;
2455
2456 if (ConfigAccess != NULL) {
2457 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);
2458 if (EFI_ERROR (Status)) {
2459 goto Done;
2460 }
2461
2462 //
2463 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary
2464 //
2465 if (mHiiPackageListUpdated) {
2466 Selection->Action = UI_ACTION_REFRESH_FORMSET;
2467 mHiiPackageListUpdated = FALSE;
2468 break;
2469 }
2470 }
2471 }
2472
2473 //
2474 // Load Questions' Value for display
2475 //
2476 Status = LoadFormSetConfig (Selection, Selection->FormSet);
2477 if (EFI_ERROR (Status)) {
2478 goto Done;
2479 }
2480
2481 if (!mFinishRetrieveCall) {
2482 //
2483 // Finish call RETRIEVE callback for this form.
2484 //
2485 mFinishRetrieveCall = TRUE;
2486
2487 if (ConfigAccess != NULL) {
2488 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);
2489 if (EFI_ERROR (Status)) {
2490 goto Done;
2491 }
2492
2493 //
2494 // IFR is updated during callback of open form, force to reparse the IFR binary
2495 //
2496 if (mHiiPackageListUpdated) {
2497 Selection->Action = UI_ACTION_REFRESH_FORMSET;
2498 mHiiPackageListUpdated = FALSE;
2499 break;
2500 }
2501 }
2502 }
2503
2504 //
2505 // Display form
2506 //
2507 Status = DisplayForm ();
2508 if (EFI_ERROR (Status)) {
2509 goto Done;
2510 }
2511
2512 //
2513 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
2514 //
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) {
2522 //
2523 // Process dynamic update ref opcode.
2524 //
2525 if (!EFI_ERROR (Status)) {
2526 Status = ProcessGotoOpCode(Statement, Selection);
2527 }
2528
2529 //
2530 // Callback return error status or status return from process goto opcode.
2531 //
2532 if (EFI_ERROR (Status)) {
2533 //
2534 // Cross reference will not be taken, restore all essential field
2535 //
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;
2541 }
2542 }
2543
2544
2545 if (!EFI_ERROR (Status) &&
2546 (Statement->Operand != EFI_IFR_REF_OP) &&
2547 ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {
2548 //
2549 // Only question value has been changed, browser will trig CHANGED callback.
2550 //
2551 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);
2552 //
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
2555 //
2556 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);
2557 }
2558 } else {
2559 //
2560 // Do the question validation.
2561 //
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);
2565 //
2566 // Verify whether question value has checked, update the ValueChanged flag in Question.
2567 //
2568 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);
2569 }
2570 }
2571
2572 //
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.
2575 //
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;
2581 }
2582
2583 if ((Statement->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {
2584 gFlagReconnect = TRUE;
2585 }
2586 }
2587 }
2588
2589 //
2590 // Check whether Exit flag is TRUE.
2591 //
2592 if (gExitRequired) {
2593 switch (gBrowserSettingScope) {
2594 case SystemLevel:
2595 Selection->Action = UI_ACTION_EXIT;
2596 break;
2597
2598 case FormSetLevel:
2599 case FormLevel:
2600 FindNextMenu (Selection, gBrowserSettingScope);
2601 break;
2602
2603 default:
2604 break;
2605 }
2606
2607 gExitRequired = FALSE;
2608 }
2609
2610 //
2611 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
2612 // for each question with callback flag.
2613 //
2614 if ((ConfigAccess != NULL) &&
2615 ((Selection->Action == UI_ACTION_EXIT) ||
2616 (Selection->Handle != mCurrentHiiHandle) ||
2617 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||
2618 (Selection->FormId != mCurrentFormId))) {
2619
2620 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);
2621 if (EFI_ERROR (Status)) {
2622 goto Done;
2623 }
2624 }
2625 } while (Selection->Action == UI_ACTION_REFRESH_FORM);
2626
2627 Done:
2628 //
2629 // Reset current form information to the initial setting when error happens or form exit.
2630 //
2631 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {
2632 mCurrentHiiHandle = NULL;
2633 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);
2634 mCurrentFormId = 0;
2635 }
2636
2637 //
2638 // Unregister notify for Form package update
2639 //
2640 mHiiDatabase->UnregisterPackageNotify (
2641 mHiiDatabase,
2642 NotifyHandle
2643 );
2644 return Status;
2645 }