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