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