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