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