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