]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg:Fix the issue FindQuestionFromProgress in SetupBrowserDxe is broken
[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
5e30b69e
DB
548 //\r
549 // treat formset as statement outside the form,get its opcode.\r
550 //\r
551 DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
552 ASSERT (DisplayStatement != NULL);\r
553\r
554 DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
555 DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
556 DisplayStatement->OpCode = gCurrentSelection->FormSet->OpCode;\r
557\r
558 InitializeListHead (&DisplayStatement->NestStatementList);\r
559 InitializeListHead (&DisplayStatement->OptionListHead);\r
560\r
561 InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
562\r
7c6c064c
ED
563 //\r
564 // Process the statement in this form.\r
565 //\r
566 Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
567 while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
568 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
569 Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
570\r
571 //\r
572 // This statement can't be show, skip it.\r
573 //\r
574 if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {\r
575 continue;\r
576 }\r
577\r
184f3a02
ED
578 //\r
579 // Check the extra attribute.\r
580 //\r
581 ExtraAttribute = ProcessQuestionExtraAttr (Statement->QuestionId);\r
582 if ((ExtraAttribute & HII_DISPLAY_SUPPRESS) != 0) {\r
583 continue;\r
584 }\r
585\r
7c6c064c
ED
586 DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
587 ASSERT (DisplayStatement != NULL);\r
588\r
589 //\r
590 // Initialize this statement and add it to the display form.\r
591 //\r
077c7aee 592 InitializeDisplayStatement(DisplayStatement, Statement);\r
7c6c064c 593\r
184f3a02
ED
594 //\r
595 // Set the extra attribute.\r
596 //\r
597 DisplayStatement->Attribute |= ExtraAttribute;\r
598\r
7c6c064c
ED
599 if (Statement->Storage != NULL) {\r
600 FormEditable = TRUE;\r
601 }\r
602\r
603 //\r
604 // Get the minimal refresh interval value for later use.\r
605 //\r
606 if ((Statement->RefreshInterval != 0) && \r
607 (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {\r
608 MinRefreshInterval = Statement->RefreshInterval;\r
609 }\r
610 }\r
611\r
612 //\r
613 // Create the periodic timer for refresh interval statement.\r
614 //\r
615 if (MinRefreshInterval != 0) {\r
616 Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent);\r
617 ASSERT_EFI_ERROR (Status);\r
618 Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND);\r
619 ASSERT_EFI_ERROR (Status);\r
620\r
621 EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
622 ASSERT (EventNode != NULL);\r
623 EventNode->RefreshEvent = RefreshIntervalEvent;\r
624 InsertTailList(&mRefreshEventList, &EventNode->Link);\r
625 }\r
626\r
790447b2
ED
627 //\r
628 // Create the refresh event process function for Form.\r
629 //\r
630 if (!CompareGuid (&gCurrentSelection->Form->RefreshGuid, &gZeroGuid)) {\r
631 CreateRefreshEventForForm (gCurrentSelection->Form);\r
632 if (gDisplayFormData.FormRefreshEvent == NULL) {\r
633 gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
634 }\r
635 }\r
636\r
7c6c064c
ED
637 //\r
638 // Update hotkey list field.\r
639 //\r
640 if (gBrowserSettingScope == SystemLevel || FormEditable) {\r
641 UpdateHotkeyList();\r
642 }\r
643}\r
644\r
645/**\r
646\r
647 Initialize the SettingChangedFlag variable in the display form.\r
648\r
649**/\r
650VOID\r
651UpdateDataChangedFlag (\r
652 VOID\r
653 )\r
654{\r
655 LIST_ENTRY *Link;\r
656 FORM_BROWSER_FORMSET *LocalFormSet;\r
657\r
658 gDisplayFormData.SettingChangedFlag = FALSE;\r
659\r
660 if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {\r
661 gDisplayFormData.SettingChangedFlag = TRUE;\r
662 return;\r
663 }\r
664\r
665 //\r
666 // Base on the system level to check whether need to show the NV flag.\r
667 // \r
668 switch (gBrowserSettingScope) {\r
669 case SystemLevel:\r
670 //\r
671 // Check the maintain list to see whether there is any change.\r
672 //\r
673 Link = GetFirstNode (&gBrowserFormSetList);\r
674 while (!IsNull (&gBrowserFormSetList, Link)) {\r
675 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
676 if (IsNvUpdateRequiredForFormSet(LocalFormSet)) {\r
677 gDisplayFormData.SettingChangedFlag = TRUE;\r
678 return;\r
679 }\r
680 Link = GetNextNode (&gBrowserFormSetList, Link);\r
681 }\r
682 break;\r
683\r
684 case FormSetLevel:\r
685 if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {\r
686 gDisplayFormData.SettingChangedFlag = TRUE;\r
687 return;\r
688 }\r
689 break;\r
690\r
691 default:\r
692 break;\r
693 }\r
694}\r
695\r
696/**\r
697\r
698 Initialize the Display form structure data.\r
699\r
700**/\r
701VOID\r
702InitializeDisplayFormData (\r
703 VOID\r
704 )\r
705{\r
706 EFI_STATUS Status;\r
707\r
708 gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;\r
709 gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;\r
710 gDisplayFormData.ImageId = 0;\r
711 gDisplayFormData.AnimationId = 0;\r
712\r
713 InitializeListHead (&gDisplayFormData.StatementListHead);\r
714 InitializeListHead (&gDisplayFormData.StatementListOSF);\r
715 InitializeListHead (&gDisplayFormData.HotKeyListHead);\r
716\r
717 Status = gBS->CreateEvent (\r
718 EVT_NOTIFY_WAIT, \r
719 TPL_CALLBACK,\r
720 SetupBrowserEmptyFunction,\r
721 NULL,\r
722 &mValueChangedEvent\r
723 );\r
724 ASSERT_EFI_ERROR (Status); \r
725}\r
726\r
727/**\r
728\r
729 Free the kotkey info saved in form data.\r
730\r
731**/\r
732VOID\r
733FreeHotkeyList (\r
734 VOID\r
735 )\r
736{\r
737 BROWSER_HOT_KEY *HotKey;\r
738 LIST_ENTRY *Link;\r
739\r
740 while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {\r
741 Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);\r
742 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
743\r
744 RemoveEntryList (&HotKey->Link);\r
745\r
746 FreePool (HotKey->KeyData);\r
747 FreePool (HotKey->HelpString);\r
748 FreePool (HotKey);\r
749 }\r
750}\r
751\r
752/**\r
753\r
754 Update the Display form structure data.\r
755\r
756**/\r
757VOID\r
758UpdateDisplayFormData (\r
759 VOID\r
760 )\r
761{\r
762 gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle;\r
763 gDisplayFormData.FormId = gCurrentSelection->FormId;\r
764 gDisplayFormData.HiiHandle = gCurrentSelection->Handle;\r
765 CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);\r
766\r
767 gDisplayFormData.Attribute = 0;\r
768 gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;\r
769 gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0;\r
770\r
771 gDisplayFormData.FormRefreshEvent = NULL;\r
772 gDisplayFormData.HighLightedStatement = NULL;\r
773\r
7c6c064c
ED
774 UpdateDataChangedFlag ();\r
775\r
776 AddStatementToDisplayForm ();\r
777}\r
778\r
779/**\r
780\r
781 Free the Display Statement structure data.\r
782\r
783 @param StatementList Point to the statement list which need to be free.\r
784\r
785**/\r
786VOID\r
787FreeStatementData (\r
788 LIST_ENTRY *StatementList\r
789 )\r
790{\r
791 LIST_ENTRY *Link;\r
792 LIST_ENTRY *OptionLink;\r
793 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
794 DISPLAY_QUESTION_OPTION *Option;\r
795\r
796 //\r
797 // Free Statements/Questions\r
798 //\r
799 while (!IsListEmpty (StatementList)) {\r
800 Link = GetFirstNode (StatementList);\r
801 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
802\r
803 //\r
804 // Free Options List\r
805 //\r
806 while (!IsListEmpty (&Statement->OptionListHead)) {\r
807 OptionLink = GetFirstNode (&Statement->OptionListHead);\r
808 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);\r
809 RemoveEntryList (&Option->Link);\r
810 FreePool (Option);\r
811 }\r
812\r
813 //\r
814 // Free nest statement List\r
815 //\r
816 if (!IsListEmpty (&Statement->NestStatementList)) {\r
817 FreeStatementData(&Statement->NestStatementList);\r
818 }\r
819\r
820 RemoveEntryList (&Statement->DisplayLink);\r
821 FreePool (Statement);\r
822 }\r
823}\r
824\r
825/**\r
826\r
827 Free the Display form structure data.\r
828\r
829**/\r
830VOID\r
831FreeDisplayFormData (\r
832 VOID\r
833 )\r
834{\r
835 FreeStatementData (&gDisplayFormData.StatementListHead);\r
836 FreeStatementData (&gDisplayFormData.StatementListOSF);\r
837\r
838 FreeRefreshEvent();\r
839\r
840 FreeHotkeyList();\r
841}\r
842\r
843/**\r
844\r
845 Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.\r
846\r
847 @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.\r
848\r
849 @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.\r
850\r
851**/\r
852FORM_BROWSER_STATEMENT *\r
853GetBrowserStatement (\r
854 IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement\r
855 )\r
856{\r
857 FORM_BROWSER_STATEMENT *Statement;\r
858 LIST_ENTRY *Link;\r
859\r
860 Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
861 while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
862 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
863\r
864 if (Statement->OpCode == DisplayStatement->OpCode) {\r
865 return Statement;\r
866 }\r
867\r
868 Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
869 }\r
870\r
871 return NULL;\r
872}\r
873\r
892eccc8
ED
874/**\r
875 Update the ValueChanged status for questions in this form.\r
876\r
877 @param FormSet FormSet data structure.\r
878 @param Form Form data structure.\r
879\r
880**/\r
881VOID \r
882UpdateStatementStatusForForm (\r
883 IN FORM_BROWSER_FORMSET *FormSet,\r
884 IN FORM_BROWSER_FORM *Form\r
885 )\r
886{\r
887 LIST_ENTRY *Link;\r
888 FORM_BROWSER_STATEMENT *Question;\r
889\r
890 Link = GetFirstNode (&Form->StatementListHead);\r
891 while (!IsNull (&Form->StatementListHead, Link)) {\r
892 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
893 Link = GetNextNode (&Form->StatementListHead, Link);\r
894\r
93551a01
ED
895 //\r
896 // For password opcode, not set the the value changed flag.\r
897 //\r
898 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
899 continue;\r
900 }\r
901\r
892eccc8
ED
902 IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
903 }\r
904}\r
905\r
906/**\r
907 Update the ValueChanged status for questions in this formset.\r
908\r
909 @param FormSet FormSet data structure.\r
910\r
911**/\r
912VOID \r
913UpdateStatementStatusForFormSet (\r
914 IN FORM_BROWSER_FORMSET *FormSet\r
915 )\r
916{\r
917 LIST_ENTRY *Link;\r
918 FORM_BROWSER_FORM *Form;\r
919\r
920 Link = GetFirstNode (&FormSet->FormListHead);\r
921 while (!IsNull (&FormSet->FormListHead, Link)) {\r
922 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
923 Link = GetNextNode (&FormSet->FormListHead, Link);\r
924\r
925 UpdateStatementStatusForForm (FormSet, Form);\r
926 }\r
927}\r
928\r
929/**\r
930 Update the ValueChanged status for questions.\r
931\r
932 @param FormSet FormSet data structure.\r
933 @param Form Form data structure.\r
934 @param SettingScope Setting Scope for Default action.\r
935\r
936**/\r
937VOID \r
938UpdateStatementStatus (\r
939 IN FORM_BROWSER_FORMSET *FormSet,\r
940 IN FORM_BROWSER_FORM *Form, \r
941 IN BROWSER_SETTING_SCOPE SettingScope\r
942 )\r
943{\r
944 LIST_ENTRY *Link;\r
945 FORM_BROWSER_FORMSET *LocalFormSet;\r
946\r
947 switch (SettingScope) {\r
948 case SystemLevel:\r
949 Link = GetFirstNode (&gBrowserFormSetList);\r
950 while (!IsNull (&gBrowserFormSetList, Link)) {\r
951 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
952 Link = GetNextNode (&gBrowserFormSetList, Link);\r
953 if (!ValidateFormSet(LocalFormSet)) {\r
954 continue;\r
955 }\r
956\r
957 UpdateStatementStatusForFormSet (LocalFormSet);\r
958 }\r
959 break;\r
960\r
961 case FormSetLevel:\r
962 UpdateStatementStatusForFormSet (FormSet);\r
963 break;\r
964\r
965 case FormLevel:\r
966 UpdateStatementStatusForForm (FormSet, Form);\r
967 break;\r
968\r
969 default:\r
970 break;\r
971 }\r
972}\r
973\r
7c6c064c
ED
974/**\r
975\r
976 Process the action request in user input.\r
977\r
978 @param Action The user input action request info.\r
979 @param DefaultId The user input default Id info.\r
980\r
981 @retval EFI_SUCESSS This function always return successfully for now.\r
982\r
983**/\r
984EFI_STATUS \r
985ProcessAction (\r
986 IN UINT32 Action,\r
987 IN UINT16 DefaultId\r
988 )\r
989{\r
7c6c064c
ED
990 //\r
991 // This is caused by use press ESC, and it should not combine with other action type.\r
992 //\r
993 if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {\r
994 FindNextMenu (gCurrentSelection, FormLevel);\r
995 return EFI_SUCCESS;\r
996 }\r
997\r
998 //\r
999 // Below is normal hotkey trigged action, these action maybe combine with each other.\r
1000 //\r
1001 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
1002 DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
1003 }\r
1004\r
1005 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
787fc2a6 1006 ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
892eccc8 1007 UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
7c6c064c
ED
1008 }\r
1009\r
1010 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
4d4deaac 1011 SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
7c6c064c
ED
1012 }\r
1013\r
1014 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
1015 gResetRequired = TRUE;\r
1016 }\r
1017\r
1018 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
1019 //\r
1020 // Form Exit without saving, Similar to ESC Key.\r
1021 // FormSet Exit without saving, Exit SendForm.\r
1022 // System Exit without saving, CallExitHandler and Exit SendForm.\r
1023 //\r
1024 DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
1025 if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {\r
1026 FindNextMenu (gCurrentSelection, gBrowserSettingScope);\r
1027 } else if (gBrowserSettingScope == SystemLevel) {\r
1028 if (ExitHandlerFunction != NULL) {\r
1029 ExitHandlerFunction ();\r
1030 }\r
1031 gCurrentSelection->Action = UI_ACTION_EXIT;\r
1032 }\r
1033 }\r
1034\r
1035 return EFI_SUCCESS;\r
1036}\r
1037\r
07d7dbae
ED
1038/**\r
1039 Check whether the formset guid is in this Hii package list.\r
1040\r
1041 @param HiiHandle The HiiHandle for this HII package list.\r
8a639069 1042 @param FormSetGuid The formset guid for the request formset.\r
07d7dbae
ED
1043\r
1044 @retval TRUE Find the formset guid.\r
1045 @retval FALSE Not found the formset guid.\r
1046\r
1047**/\r
1048BOOLEAN\r
1049GetFormsetGuidFromHiiHandle (\r
1050 IN EFI_HII_HANDLE HiiHandle,\r
1051 IN EFI_GUID *FormSetGuid\r
1052 )\r
1053{\r
1054 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1055 UINTN BufferSize;\r
1056 UINT32 Offset;\r
1057 UINT32 Offset2;\r
1058 UINT32 PackageListLength;\r
1059 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1060 UINT8 *Package;\r
1061 UINT8 *OpCodeData;\r
1062 EFI_STATUS Status;\r
1063 BOOLEAN FindGuid;\r
1064\r
1065 BufferSize = 0;\r
1066 HiiPackageList = NULL;\r
1067 FindGuid = FALSE;\r
1068 \r
1069 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1070 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1071 HiiPackageList = AllocatePool (BufferSize);\r
1072 ASSERT (HiiPackageList != NULL);\r
1073\r
1074 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1075 }\r
1076 if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
1077 return FALSE;\r
1078 }\r
1079\r
1080 //\r
1081 // Get Form package from this HII package List\r
1082 //\r
1083 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1084 Offset2 = 0;\r
1085 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
1086\r
1087 while (Offset < PackageListLength) {\r
1088 Package = ((UINT8 *) HiiPackageList) + Offset;\r
1089 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
1090 Offset += PackageHeader.Length;\r
1091\r
1092 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1093 //\r
1094 // Search FormSet in this Form Package\r
1095 //\r
1096 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
1097 while (Offset2 < PackageHeader.Length) {\r
1098 OpCodeData = Package + Offset2;\r
1099\r
1100 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
1101 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){\r
1102 FindGuid = TRUE;\r
1103 break;\r
1104 }\r
1105 }\r
1106\r
1107 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
1108 }\r
1109 }\r
1110 if (FindGuid) {\r
1111 break;\r
1112 }\r
1113 }\r
1114\r
1115 FreePool (HiiPackageList);\r
1116\r
1117 return FindGuid;\r
1118}\r
7c6c064c
ED
1119\r
1120/**\r
1121 Find HII Handle in the HII database associated with given Device Path.\r
1122\r
1123 If DevicePath is NULL, then ASSERT.\r
1124\r
1125 @param DevicePath Device Path associated with the HII package list\r
1126 handle.\r
07d7dbae 1127 @param FormsetGuid The formset guid for this formset.\r
7c6c064c
ED
1128\r
1129 @retval Handle HII package list Handle associated with the Device\r
1130 Path.\r
1131 @retval NULL Hii Package list handle is not found.\r
1132\r
1133**/\r
1134EFI_HII_HANDLE\r
7c6c064c 1135DevicePathToHiiHandle (\r
07d7dbae
ED
1136 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1137 IN EFI_GUID *FormsetGuid\r
7936fb6a 1138 )\r
1139{\r
7c6c064c
ED
1140 EFI_STATUS Status;\r
1141 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
7c6c064c
ED
1142 UINTN Index;\r
1143 EFI_HANDLE Handle;\r
1144 EFI_HANDLE DriverHandle;\r
1145 EFI_HII_HANDLE *HiiHandles;\r
1146 EFI_HII_HANDLE HiiHandle;\r
1147\r
1148 ASSERT (DevicePath != NULL);\r
1149\r
1150 TmpDevicePath = DevicePath;\r
1151 //\r
1152 // Locate Device Path Protocol handle buffer\r
1153 //\r
1154 Status = gBS->LocateDevicePath (\r
1155 &gEfiDevicePathProtocolGuid,\r
1156 &TmpDevicePath,\r
1157 &DriverHandle\r
1158 );\r
1159 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
1160 return NULL;\r
1161 }\r
7936fb6a 1162\r
1163 //\r
7c6c064c 1164 // Retrieve all HII Handles from HII database\r
7936fb6a 1165 //\r
07d7dbae
ED
1166 HiiHandles = HiiGetHiiHandles (NULL);\r
1167 if (HiiHandles == NULL) {\r
7c6c064c
ED
1168 return NULL;\r
1169 }\r
b9feb4bd 1170\r
7936fb6a 1171 //\r
7c6c064c 1172 // Search Hii Handle by Driver Handle\r
7936fb6a 1173 //\r
7c6c064c 1174 HiiHandle = NULL;\r
07d7dbae 1175 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
7c6c064c
ED
1176 Status = mHiiDatabase->GetPackageListHandle (\r
1177 mHiiDatabase,\r
1178 HiiHandles[Index],\r
1179 &Handle\r
1180 );\r
1181 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
07d7dbae
ED
1182 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {\r
1183 HiiHandle = HiiHandles[Index];\r
1184 break;\r
1185 }\r
1186\r
1187 if (HiiHandle != NULL) {\r
1188 break;\r
1189 }\r
7c6c064c
ED
1190 }\r
1191 }\r
1192\r
1193 FreePool (HiiHandles);\r
1194 return HiiHandle;\r
1195}\r
1196\r
1197/**\r
1198 Find HII Handle in the HII database associated with given form set guid.\r
1199\r
1200 If FormSetGuid is NULL, then ASSERT.\r
1201\r
1202 @param ComparingGuid FormSet Guid associated with the HII package list\r
1203 handle.\r
1204\r
1205 @retval Handle HII package list Handle associated with the Device\r
1206 Path.\r
1207 @retval NULL Hii Package list handle is not found.\r
7936fb6a 1208\r
7c6c064c
ED
1209**/\r
1210EFI_HII_HANDLE\r
1211FormSetGuidToHiiHandle (\r
1212 EFI_GUID *ComparingGuid\r
1213 )\r
1214{\r
1215 EFI_HII_HANDLE *HiiHandles;\r
7c6c064c 1216 EFI_HII_HANDLE HiiHandle;\r
07d7dbae 1217 UINTN Index;\r
7c6c064c
ED
1218\r
1219 ASSERT (ComparingGuid != NULL);\r
1220\r
1221 HiiHandle = NULL;\r
7936fb6a 1222 //\r
7c6c064c 1223 // Get all the Hii handles\r
7936fb6a 1224 //\r
7c6c064c
ED
1225 HiiHandles = HiiGetHiiHandles (NULL);\r
1226 ASSERT (HiiHandles != NULL);\r
25361615
ED
1227\r
1228 //\r
7c6c064c 1229 // Search for formset of each class type\r
25361615 1230 //\r
7c6c064c 1231 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
07d7dbae
ED
1232 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
1233 HiiHandle = HiiHandles[Index];\r
1234 break;\r
7c6c064c
ED
1235 }\r
1236\r
07d7dbae
ED
1237 if (HiiHandle != NULL) {\r
1238 break;\r
7c6c064c 1239 }\r
7936fb6a 1240 }\r
1241\r
7c6c064c 1242 FreePool (HiiHandles);\r
7936fb6a 1243\r
7c6c064c 1244 return HiiHandle;\r
7936fb6a 1245}\r
1246\r
1247/**\r
7c6c064c
ED
1248 check how to process the changed data in current form or form set.\r
1249\r
1250 @param Selection On input, Selection tell setup browser the information\r
1251 about the Selection, form and formset to be displayed.\r
1252 On output, Selection return the screen item that is selected\r
1253 by user.\r
7936fb6a 1254\r
7c6c064c 1255 @param Scope Data save or discard scope, form or formset.\r
7936fb6a 1256\r
7c6c064c
ED
1257 @retval TRUE Success process the changed data, will return to the parent form.\r
1258 @retval FALSE Reject to process the changed data, will stay at current form.\r
7936fb6a 1259**/\r
7c6c064c
ED
1260BOOLEAN\r
1261ProcessChangedData (\r
1262 IN OUT UI_MENU_SELECTION *Selection,\r
1263 IN BROWSER_SETTING_SCOPE Scope\r
7936fb6a 1264 )\r
1265{\r
4d4deaac
ED
1266 BOOLEAN RetValue;\r
1267 EFI_STATUS Status;\r
7936fb6a 1268\r
7c6c064c
ED
1269 RetValue = TRUE;\r
1270 switch (mFormDisplay->ConfirmDataChange()) {\r
6307a8b6 1271 case BROWSER_ACTION_DISCARD:\r
7c6c064c
ED
1272 DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
1273 break;\r
1274 \r
6307a8b6 1275 case BROWSER_ACTION_SUBMIT:\r
4d4deaac
ED
1276 Status = SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
1277 if (EFI_ERROR (Status)) {\r
1278 RetValue = FALSE;\r
1279 }\r
7c6c064c 1280 break;\r
7936fb6a 1281\r
6307a8b6 1282 case BROWSER_ACTION_NONE:\r
7c6c064c
ED
1283 RetValue = FALSE;\r
1284 break;\r
b9feb4bd 1285\r
7c6c064c
ED
1286 default:\r
1287 //\r
1288 // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
1289 //\r
1290 RetValue = FALSE;\r
1291 break;\r
1292 }\r
1293\r
1294 return RetValue;\r
7936fb6a 1295}\r
1296\r
1297/**\r
7c6c064c
ED
1298 Find parent formset menu(the first menu which has different formset) for current menu.\r
1299 If not find, just return to the first menu.\r
7936fb6a 1300\r
7c6c064c 1301 @param Selection The selection info.\r
7936fb6a 1302\r
1303**/\r
7c6c064c
ED
1304VOID\r
1305FindParentFormSet (\r
1306 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1307 )\r
1308{\r
7c6c064c
ED
1309 FORM_ENTRY_INFO *CurrentMenu;\r
1310 FORM_ENTRY_INFO *ParentMenu;\r
25361615 1311\r
7c6c064c 1312 CurrentMenu = Selection->CurrentMenu;\r
93551a01 1313 ParentMenu = UiFindParentMenu(CurrentMenu, FormSetLevel);\r
7c6c064c
ED
1314\r
1315 if (ParentMenu != NULL) {\r
1316 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
1317 Selection->Handle = ParentMenu->HiiHandle;\r
1318 Selection->FormId = ParentMenu->FormId;\r
1319 Selection->QuestionId = ParentMenu->QuestionId;\r
1320 } else {\r
1321 Selection->FormId = CurrentMenu->FormId;\r
1322 Selection->QuestionId = CurrentMenu->QuestionId;\r
1323 }\r
7936fb6a 1324\r
7c6c064c 1325 Selection->Statement = NULL;\r
7936fb6a 1326}\r
1327\r
1328/**\r
7c6c064c 1329 Process the goto op code, update the info in the selection structure.\r
7936fb6a 1330\r
7c6c064c
ED
1331 @param Statement The statement belong to goto op code.\r
1332 @param Selection The selection info.\r
1333\r
1334 @retval EFI_SUCCESS The menu process successfully.\r
1335 @return Other value if the process failed.\r
7936fb6a 1336**/\r
7c6c064c
ED
1337EFI_STATUS\r
1338ProcessGotoOpCode (\r
1339 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
1340 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1341 )\r
1342{\r
7c6c064c
ED
1343 CHAR16 *StringPtr;\r
1344 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1345 FORM_BROWSER_FORM *RefForm;\r
1346 EFI_STATUS Status;\r
1347 EFI_HII_HANDLE HiiHandle;\r
1348 \r
1349 Status = EFI_SUCCESS;\r
1350 StringPtr = NULL;\r
1351 HiiHandle = NULL;\r
25361615 1352\r
b9feb4bd 1353 //\r
7c6c064c 1354 // Prepare the device path check, get the device path info first.\r
b9feb4bd 1355 //\r
7c6c064c
ED
1356 if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
1357 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
25361615 1358 }\r
b9feb4bd 1359\r
7c6c064c
ED
1360 //\r
1361 // Check whether the device path string is a valid string.\r
1362 //\r
798e4d22 1363 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
7c6c064c
ED
1364 if (Selection->Form->ModalForm) {\r
1365 return Status;\r
1366 }\r
1367\r
25361615 1368 //\r
7c6c064c 1369 // Goto another Hii Package list\r
25361615 1370 //\r
7c6c064c
ED
1371 if (mPathFromText != NULL) {\r
1372 DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
1373 if (DevicePath != NULL) {\r
07d7dbae 1374 HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
7c6c064c
ED
1375 FreePool (DevicePath);\r
1376 }\r
1377 FreePool (StringPtr);\r
1378 } else {\r
7936fb6a 1379 //\r
7c6c064c 1380 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
7936fb6a 1381 //\r
4d4deaac 1382 PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);\r
7c6c064c
ED
1383 FreePool (StringPtr);\r
1384 return Status;\r
1385 }\r
25361615 1386\r
7c6c064c
ED
1387 if (HiiHandle != Selection->Handle) {\r
1388 //\r
1389 // Goto another Formset, check for uncommitted data\r
1390 //\r
1391 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
1392 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
1393 if (!ProcessChangedData(Selection, FormSetLevel)) {\r
1394 return EFI_SUCCESS;\r
7936fb6a 1395 }\r
7936fb6a 1396 }\r
1397 }\r
7936fb6a 1398\r
7c6c064c
ED
1399 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1400 Selection->Handle = HiiHandle;\r
1401 if (Selection->Handle == NULL) {\r
1402 //\r
1403 // If target Hii Handle not found, exit current formset.\r
1404 //\r
1405 FindParentFormSet(Selection);\r
1406 return EFI_SUCCESS;\r
7936fb6a 1407 }\r
1408\r
7c6c064c
ED
1409 CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
1410 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1411 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1412 } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
1413 if (Selection->Form->ModalForm) {\r
1414 return Status;\r
1415 }\r
1416 if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {\r
7936fb6a 1417 //\r
7c6c064c 1418 // Goto another Formset, check for uncommitted data\r
7936fb6a 1419 //\r
7c6c064c
ED
1420 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
1421 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
1422 if (!ProcessChangedData(Selection, FormSetLevel)) {\r
1423 return EFI_SUCCESS;\r
1424 }\r
7936fb6a 1425 }\r
7c6c064c 1426 }\r
7936fb6a 1427\r
7c6c064c
ED
1428 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1429 Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
1430 if (Selection->Handle == NULL) {\r
1431 //\r
1432 // If target Hii Handle not found, exit current formset.\r
1433 //\r
1434 FindParentFormSet(Selection);\r
1435 return EFI_SUCCESS;\r
1436 }\r
7936fb6a 1437\r
7c6c064c
ED
1438 CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
1439 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1440 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1441 } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
1442 //\r
1443 // Goto another Form, check for uncommitted data\r
1444 //\r
1445 if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {\r
1446 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {\r
1447 if (!ProcessChangedData (Selection, FormLevel)) {\r
1448 return EFI_SUCCESS;\r
1449 }\r
1450 }\r
1451 }\r
7936fb6a 1452\r
7c6c064c
ED
1453 RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
1454 if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
1455 if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
1456 //\r
1457 // Form is suppressed. \r
1458 //\r
4d4deaac 1459 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
7c6c064c
ED
1460 return EFI_SUCCESS;\r
1461 }\r
7936fb6a 1462 }\r
7936fb6a 1463\r
7c6c064c
ED
1464 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1465 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1466 } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
1467 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1468 }\r
25361615 1469\r
7c6c064c 1470 return Status;\r
7936fb6a 1471}\r
1472\r
1473\r
1474/**\r
7c6c064c 1475 Process Question Config.\r
7936fb6a 1476\r
7c6c064c
ED
1477 @param Selection The UI menu selection.\r
1478 @param Question The Question to be peocessed.\r
7936fb6a 1479\r
7c6c064c
ED
1480 @retval EFI_SUCCESS Question Config process success.\r
1481 @retval Other Question Config process fail.\r
7936fb6a 1482\r
1483**/\r
1484EFI_STATUS\r
7c6c064c
ED
1485ProcessQuestionConfig (\r
1486 IN UI_MENU_SELECTION *Selection,\r
1487 IN FORM_BROWSER_STATEMENT *Question\r
7936fb6a 1488 )\r
1489{\r
7c6c064c
ED
1490 EFI_STATUS Status;\r
1491 CHAR16 *ConfigResp;\r
1492 CHAR16 *Progress;\r
7936fb6a 1493\r
7c6c064c
ED
1494 if (Question->QuestionConfig == 0) {\r
1495 return EFI_SUCCESS;\r
1496 }\r
7936fb6a 1497\r
7c6c064c
ED
1498 //\r
1499 // Get <ConfigResp>\r
1500 //\r
1501 ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
1502 if (ConfigResp == NULL) {\r
1503 return EFI_NOT_FOUND;\r
40ad4b1a
ED
1504 } else if (ConfigResp[0] == L'\0') {\r
1505 return EFI_SUCCESS;\r
7c6c064c 1506 }\r
7936fb6a 1507\r
7c6c064c
ED
1508 //\r
1509 // Send config to Configuration Driver\r
1510 //\r
7248790e
ED
1511 Status = mHiiConfigRouting->RouteConfig (\r
1512 mHiiConfigRouting,\r
7c6c064c
ED
1513 ConfigResp,\r
1514 &Progress\r
1515 );\r
7936fb6a 1516\r
7c6c064c 1517 return Status;\r
7936fb6a 1518}\r
1519\r
7936fb6a 1520/**\r
1521\r
7c6c064c 1522 Process the user input data.\r
d66e6c16 1523\r
7c6c064c 1524 @param UserInput The user input data.\r
d66e6c16 1525\r
7936fb6a 1526 @retval EFI_SUCESSS This function always return successfully for now.\r
1527\r
1528**/\r
1529EFI_STATUS\r
7c6c064c 1530ProcessUserInput (\r
42645c3d 1531 IN USER_INPUT *UserInput\r
7936fb6a 1532 )\r
1533{\r
7c6c064c
ED
1534 EFI_STATUS Status;\r
1535 FORM_BROWSER_STATEMENT *Statement;\r
25361615 1536\r
42645c3d
ED
1537 Status = EFI_SUCCESS;\r
1538 Statement = NULL;\r
7936fb6a 1539\r
1540 //\r
7c6c064c 1541 // When Exit from FormDisplay function, one of the below two cases must be true.\r
7936fb6a 1542 //\r
7c6c064c 1543 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
7936fb6a 1544\r
b9feb4bd 1545 //\r
7c6c064c 1546 // Remove the last highligh question id, this id will update when show next form.\r
b9feb4bd 1547 //\r
7c6c064c 1548 gCurrentSelection->QuestionId = 0;\r
42645c3d
ED
1549 if (UserInput->SelectedStatement != NULL){\r
1550 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1551 ASSERT (Statement != NULL);\r
1552\r
1553 //\r
1554 // This question is the current user select one,record it and later\r
1555 // show it as the highlight question.\r
1556 //\r
1557 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1558 //\r
1559 // For statement like text, actio, it not has question id.\r
1560 // So use FakeQuestionId to save the question.\r
1561 //\r
1562 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1563 mCurFakeQestId = Statement->FakeQuestionId;\r
1564 } else {\r
1565 mCurFakeQestId = 0;\r
1566 }\r
1567 }\r
7936fb6a 1568\r
7c6c064c
ED
1569 //\r
1570 // First process the Action field in USER_INPUT.\r
1571 //\r
1572 if (UserInput->Action != 0) {\r
1573 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
7c6c064c 1574 gCurrentSelection->Statement = NULL;\r
7c6c064c 1575 } else {\r
7c6c064c 1576 ASSERT (Statement != NULL);\r
7c6c064c 1577 gCurrentSelection->Statement = Statement;\r
7c6c064c
ED
1578 switch (Statement->Operand) {\r
1579 case EFI_IFR_REF_OP:\r
1580 Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
1581 break;\r
1582 \r
1583 case EFI_IFR_ACTION_OP:\r
1584 //\r
1585 // Process the Config string <ConfigResp>\r
1586 //\r
1587 Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
1588 break;\r
1589 \r
1590 case EFI_IFR_RESET_BUTTON_OP:\r
7936fb6a 1591 //\r
7c6c064c 1592 // Reset Question to default value specified by DefaultId\r
7936fb6a 1593 //\r
787fc2a6 1594 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
892eccc8 1595 UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
7c6c064c
ED
1596 break;\r
1597\r
1598 default:\r
1599 switch (Statement->Operand) {\r
1600 case EFI_IFR_STRING_OP:\r
1601 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1602 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1603 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1604 FreePool (UserInput->InputValue.Buffer);\r
1605 break;\r
1606\r
1607 case EFI_IFR_PASSWORD_OP:\r
1608 if (UserInput->InputValue.Buffer == NULL) {\r
1609 //\r
1610 // User not input new password, just return.\r
1611 //\r
1612 break;\r
1613 }\r
8b0fc5c1 1614\r
7c6c064c
ED
1615 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1616 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1617 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1618 FreePool (UserInput->InputValue.Buffer);\r
8b0fc5c1 1619 //\r
7c6c064c 1620 // Two password match, send it to Configuration Driver\r
8b0fc5c1 1621 //\r
7c6c064c
ED
1622 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
1623 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
1624 //\r
1625 // Clean the value after saved it.\r
1626 //\r
1627 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
1628 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
1629 } else {\r
1630 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
1631 }\r
1632 break;\r
1633\r
1634 case EFI_IFR_ORDERED_LIST_OP:\r
1635 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
1636 break;\r
1637\r
1638 default:\r
1639 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
1640 break;\r
1641 }\r
7c6c064c 1642 break;\r
7936fb6a 1643 }\r
7936fb6a 1644 }\r
1645\r
7936fb6a 1646 return Status;\r
1647}\r
1648\r
1649/**\r
7936fb6a 1650\r
7c6c064c 1651 Display form and wait for user to select one menu option, then return it.\r
7936fb6a 1652\r
7c6c064c 1653 @retval EFI_SUCESSS This function always return successfully for now.\r
48a9d5f7
LG
1654\r
1655**/\r
7c6c064c
ED
1656EFI_STATUS\r
1657DisplayForm (\r
48a9d5f7
LG
1658 VOID\r
1659 )\r
1660{\r
7c6c064c
ED
1661 EFI_STATUS Status;\r
1662 USER_INPUT UserInput;\r
1663 FORM_ENTRY_INFO *CurrentMenu;\r
48a9d5f7 1664\r
7c6c064c 1665 ZeroMem (&UserInput, sizeof (USER_INPUT));\r
48a9d5f7
LG
1666\r
1667 //\r
7c6c064c 1668 // Update the menu history data.\r
48a9d5f7 1669 //\r
7c6c064c
ED
1670 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
1671 if (CurrentMenu == NULL) {\r
48a9d5f7 1672 //\r
7c6c064c 1673 // Current menu not found, add it to the menu tree\r
25361615 1674 //\r
7c6c064c
ED
1675 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
1676 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
1677 ASSERT (CurrentMenu != NULL);\r
1678 }\r
4d4deaac
ED
1679\r
1680 //\r
1681 // Back up the form view history data for this form.\r
1682 //\r
1683 UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
1684\r
7c6c064c 1685 gCurrentSelection->CurrentMenu = CurrentMenu;\r
48a9d5f7 1686\r
7c6c064c 1687 if (gCurrentSelection->QuestionId == 0) {\r
48a9d5f7 1688 //\r
7c6c064c 1689 // Highlight not specified, fetch it from cached menu\r
48a9d5f7 1690 //\r
7c6c064c 1691 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
48a9d5f7 1692 }\r
25361615 1693\r
7c6c064c
ED
1694 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
1695 if (EFI_ERROR (Status)) {\r
1696 return Status;\r
b9feb4bd 1697 }\r
7936fb6a 1698\r
7c6c064c 1699 UpdateDisplayFormData ();\r
25361615 1700\r
4d4deaac 1701 ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
7c6c064c 1702 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
42645c3d 1703 if (EFI_ERROR (Status)) {\r
7c6c064c
ED
1704 FreeDisplayFormData();\r
1705 return Status;\r
1706 }\r
25361615 1707\r
42645c3d 1708 Status = ProcessUserInput (&UserInput);\r
7c6c064c 1709 FreeDisplayFormData();\r
7c6c064c 1710 return Status;\r
7936fb6a 1711}\r
1712\r
1713/**\r
1714 Functions which are registered to receive notification of\r
1715 database events have this prototype. The actual event is encoded\r
1716 in NotifyType. The following table describes how PackageType,\r
1717 PackageGuid, Handle, and Package are used for each of the\r
1718 notification types.\r
1719\r
1720 @param PackageType Package type of the notification.\r
1721\r
1722 @param PackageGuid If PackageType is\r
1723 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
1724 the pointer to the GUID from the Guid\r
1725 field of EFI_HII_PACKAGE_GUID_HEADER.\r
1726 Otherwise, it must be NULL.\r
1727\r
1728 @param Package Points to the package referred to by the\r
1729 notification Handle The handle of the package\r
1730 list which contains the specified package.\r
1731\r
1732 @param Handle The HII handle.\r
1733\r
1734 @param NotifyType The type of change concerning the\r
1735 database. See\r
1736 EFI_HII_DATABASE_NOTIFY_TYPE.\r
1737\r
1738**/\r
1739EFI_STATUS\r
6d3ea23f 1740EFIAPI\r
7936fb6a 1741FormUpdateNotify (\r
1742 IN UINT8 PackageType,\r
1743 IN CONST EFI_GUID *PackageGuid,\r
1744 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
1745 IN EFI_HII_HANDLE Handle,\r
1746 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
1747 )\r
1748{\r
1749 mHiiPackageListUpdated = TRUE;\r
1750\r
1751 return EFI_SUCCESS;\r
1752}\r
1753\r
b18e7050 1754/**\r
7c6c064c 1755 Update the NV flag info for this form set.\r
b18e7050
ED
1756\r
1757 @param FormSet FormSet data structure.\r
1758\r
b18e7050 1759**/\r
7c6c064c
ED
1760BOOLEAN\r
1761IsNvUpdateRequiredForFormSet (\r
b18e7050
ED
1762 IN FORM_BROWSER_FORMSET *FormSet\r
1763 )\r
1764{\r
1765 LIST_ENTRY *Link;\r
1766 FORM_BROWSER_FORM *Form;\r
7c6c064c
ED
1767 BOOLEAN RetVal;\r
1768\r
1769 //\r
1770 // Not finished question initialization, return FALSE.\r
1771 //\r
1772 if (!FormSet->QuestionInited) {\r
1773 return FALSE;\r
1774 }\r
1775\r
1776 RetVal = FALSE;\r
b18e7050
ED
1777\r
1778 Link = GetFirstNode (&FormSet->FormListHead);\r
1779 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1780 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1781\r
7c6c064c
ED
1782 RetVal = IsNvUpdateRequiredForForm(Form);\r
1783 if (RetVal) {\r
1784 break;\r
b9feb4bd
ED
1785 }\r
1786\r
25361615 1787 Link = GetNextNode (&FormSet->FormListHead, Link);\r
b9feb4bd
ED
1788 }\r
1789\r
7c6c064c
ED
1790 return RetVal;\r
1791}\r
1792\r
1793/**\r
1794 Update the NvUpdateRequired flag for a form.\r
1795\r
1796 @param Form Form data structure.\r
1797\r
1798**/\r
1799BOOLEAN\r
1800IsNvUpdateRequiredForForm (\r
1801 IN FORM_BROWSER_FORM *Form\r
1802 )\r
1803{\r
1804 LIST_ENTRY *Link;\r
1805 FORM_BROWSER_STATEMENT *Statement;\r
1806\r
1807 Link = GetFirstNode (&Form->StatementListHead);\r
1808 while (!IsNull (&Form->StatementListHead, Link)) {\r
1809 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1810\r
1811 if (Statement->ValueChanged) {\r
1812 return TRUE;\r
1813 }\r
1814\r
1815 Link = GetNextNode (&Form->StatementListHead, Link);\r
1816 }\r
1817\r
b18e7050
ED
1818 return FALSE;\r
1819}\r
1820\r
b18e7050
ED
1821/**\r
1822 Find menu which will show next time.\r
1823\r
1824 @param Selection On input, Selection tell setup browser the information\r
1825 about the Selection, form and formset to be displayed.\r
1826 On output, Selection return the screen item that is selected\r
1827 by user.\r
7c6c064c
ED
1828 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
1829 else, we need to exit current formset.\r
b18e7050 1830 \r
7c6c064c
ED
1831 @retval TRUE Exit current form.\r
1832 @retval FALSE User press ESC and keep in current form.\r
b18e7050
ED
1833**/\r
1834BOOLEAN\r
1835FindNextMenu (\r
7c6c064c 1836 IN OUT UI_MENU_SELECTION *Selection,\r
93551a01 1837 IN BROWSER_SETTING_SCOPE SettingLevel\r
b18e7050
ED
1838 )\r
1839{\r
7c6c064c
ED
1840 FORM_ENTRY_INFO *CurrentMenu;\r
1841 FORM_ENTRY_INFO *ParentMenu;\r
1842 BROWSER_SETTING_SCOPE Scope;\r
b18e7050
ED
1843 \r
1844 CurrentMenu = Selection->CurrentMenu;\r
7c6c064c 1845 Scope = FormSetLevel;\r
b18e7050 1846\r
93551a01
ED
1847 ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
1848 while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
1849 ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
1850 }\r
25361615 1851\r
93551a01
ED
1852 if (ParentMenu != NULL) {\r
1853 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1854 Scope = FormLevel;\r
7c6c064c
ED
1855 } else {\r
1856 Scope = FormSetLevel;\r
b18e7050 1857 }\r
25361615
ED
1858 }\r
1859\r
b9feb4bd 1860 //\r
7c6c064c 1861 // Form Level Check whether the data is changed.\r
b9feb4bd 1862 //\r
7c6c064c
ED
1863 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
1864 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
4d4deaac 1865 if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
25361615
ED
1866 return FALSE;\r
1867 }\r
7c6c064c 1868 }\r
b9feb4bd 1869\r
7c6c064c
ED
1870 if (ParentMenu != NULL) {\r
1871 //\r
1872 // ParentMenu is found. Then, go to it.\r
1873 //\r
1874 if (Scope == FormLevel) {\r
1875 Selection->Action = UI_ACTION_REFRESH_FORM;\r
25361615 1876 } else {\r
7c6c064c
ED
1877 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1878 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
1879 Selection->Handle = ParentMenu->HiiHandle;\r
25361615 1880 }\r
25361615 1881\r
7c6c064c
ED
1882 Selection->Statement = NULL;\r
1883\r
1884 Selection->FormId = ParentMenu->FormId;\r
1885 Selection->QuestionId = ParentMenu->QuestionId;\r
1886\r
1887 //\r
1888 // Clear highlight record for this menu\r
1889 //\r
25361615 1890 CurrentMenu->QuestionId = 0;\r
7c6c064c 1891 return FALSE;\r
25361615
ED
1892 }\r
1893\r
7c6c064c
ED
1894 //\r
1895 // Current in root page, exit the SendForm\r
1896 //\r
25361615 1897 Selection->Action = UI_ACTION_EXIT;\r
7c6c064c 1898\r
b18e7050
ED
1899 return TRUE;\r
1900}\r
1901\r
f2e7732e
ED
1902/**\r
1903 Reconnect the controller.\r
1904\r
1905 @param DriverHandle The controller handle which need to be reconnect.\r
1906\r
1907 @retval TRUE do the reconnect behavior success.\r
1908 @retval FALSE do the reconnect behavior failed.\r
1909 \r
1910**/\r
1911BOOLEAN\r
1912ReconnectController (\r
1913 IN EFI_HANDLE DriverHandle\r
1914 )\r
1915{\r
1916 EFI_STATUS Status;\r
1917\r
1918 Status = gBS->DisconnectController(DriverHandle, NULL, NULL);\r
1919 if (!EFI_ERROR (Status)) {\r
1920 Status = gBS->ConnectController(DriverHandle, NULL, NULL, TRUE);\r
1921 }\r
1922\r
1923 return Status == EFI_SUCCESS;\r
1924}\r
1925\r
b18e7050
ED
1926/**\r
1927 Call the call back function for the question and process the return action.\r
1928\r
1929 @param Selection On input, Selection tell setup browser the information\r
1930 about the Selection, form and formset to be displayed.\r
1931 On output, Selection return the screen item that is selected\r
1932 by user.\r
798e4d22
ED
1933 @param FormSet The formset this question belong to.\r
1934 @param Form The form this question belong to.\r
b18e7050
ED
1935 @param Question The Question which need to call.\r
1936 @param Action The action request.\r
1937 @param SkipSaveOrDiscard Whether skip save or discard action.\r
1938\r
1939 @retval EFI_SUCCESS The call back function excutes successfully.\r
1940 @return Other value if the call back function failed to excute. \r
1941**/\r
1942EFI_STATUS \r
1943ProcessCallBackFunction (\r
1944 IN OUT UI_MENU_SELECTION *Selection,\r
798e4d22
ED
1945 IN FORM_BROWSER_FORMSET *FormSet,\r
1946 IN FORM_BROWSER_FORM *Form,\r
b18e7050
ED
1947 IN FORM_BROWSER_STATEMENT *Question,\r
1948 IN EFI_BROWSER_ACTION Action,\r
1949 IN BOOLEAN SkipSaveOrDiscard\r
1950 )\r
1951{\r
1952 EFI_STATUS Status;\r
fc2e7502 1953 EFI_STATUS InternalStatus;\r
b18e7050
ED
1954 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
1955 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1956 EFI_HII_VALUE *HiiValue;\r
1957 EFI_IFR_TYPE_VALUE *TypeValue;\r
1958 FORM_BROWSER_STATEMENT *Statement;\r
1959 BOOLEAN SubmitFormIsRequired;\r
b18e7050
ED
1960 BOOLEAN DiscardFormIsRequired;\r
1961 BOOLEAN NeedExit;\r
1962 LIST_ENTRY *Link;\r
48a9d5f7 1963 BROWSER_SETTING_SCOPE SettingLevel;\r
e6cc2ab3
ED
1964 EFI_IFR_TYPE_VALUE BackUpValue;\r
1965 UINT8 *BackUpBuffer;\r
061d5462 1966 CHAR16 *NewString;\r
b18e7050 1967\r
798e4d22 1968 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 1969 SubmitFormIsRequired = FALSE;\r
48a9d5f7 1970 SettingLevel = FormSetLevel;\r
b18e7050
ED
1971 DiscardFormIsRequired = FALSE;\r
1972 NeedExit = FALSE;\r
1973 Status = EFI_SUCCESS;\r
1974 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 1975 BackUpBuffer = NULL;\r
b18e7050
ED
1976\r
1977 if (ConfigAccess == NULL) {\r
1978 return EFI_SUCCESS;\r
1979 }\r
1980\r
798e4d22
ED
1981 Link = GetFirstNode (&Form->StatementListHead);\r
1982 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 1983 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 1984 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
1985\r
1986 //\r
1987 // if Question != NULL, only process the question. Else, process all question in this form.\r
1988 //\r
1989 if ((Question != NULL) && (Statement != Question)) {\r
1990 continue;\r
1991 }\r
1992 \r
1993 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
1994 continue;\r
1995 }\r
1996\r
1997 //\r
1998 // Check whether Statement is disabled.\r
1999 //\r
31585af4 2000 if (Statement->Expression != NULL) {\r
798e4d22 2001 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
2002 continue;\r
2003 }\r
2004 }\r
2005\r
2006 HiiValue = &Statement->HiiValue;\r
2007 TypeValue = &HiiValue->Value;\r
2008 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2009 //\r
2010 // For OrderedList, passing in the value buffer to Callback()\r
2011 //\r
2012 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2013 }\r
e6cc2ab3
ED
2014\r
2015 //\r
2016 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
2017 //\r
2018 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2019 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2020 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
523f48e7 2021 ASSERT (BackUpBuffer != NULL);\r
e6cc2ab3
ED
2022 } else {\r
2023 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
2024 }\r
2025 }\r
2026\r
b18e7050
ED
2027 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2028 Status = ConfigAccess->Callback (\r
2029 ConfigAccess,\r
2030 Action,\r
2031 Statement->QuestionId,\r
2032 HiiValue->Type,\r
2033 TypeValue,\r
2034 &ActionRequest\r
2035 );\r
2036 if (!EFI_ERROR (Status)) {\r
bfae1330
ED
2037 //\r
2038 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
2039 //\r
2040 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2041 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2042 ASSERT (NewString != NULL);\r
2043\r
2044 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2045 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2046 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2047 } else {\r
2048 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2049 }\r
2050 FreePool (NewString);\r
2051 }\r
2052\r
3a4e7a3e
ED
2053 //\r
2054 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
2055 //\r
bfae1330
ED
2056 switch (Action) {\r
2057 case EFI_BROWSER_ACTION_CHANGED:\r
3a4e7a3e
ED
2058 switch (ActionRequest) {\r
2059 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 2060 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 2061 gResetRequired = TRUE;\r
7c6c064c 2062 NeedExit = TRUE;\r
3a4e7a3e 2063 break;\r
b18e7050 2064\r
3a4e7a3e
ED
2065 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2066 SubmitFormIsRequired = TRUE;\r
7c6c064c 2067 NeedExit = TRUE;\r
3a4e7a3e 2068 break;\r
b18e7050 2069\r
3a4e7a3e 2070 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 2071 DiscardFormIsRequired = TRUE;\r
7c6c064c 2072 NeedExit = TRUE;\r
3a4e7a3e 2073 break;\r
b18e7050 2074\r
3a4e7a3e
ED
2075 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
2076 SubmitFormIsRequired = TRUE;\r
2077 SettingLevel = FormLevel;\r
2078 NeedExit = TRUE;\r
2079 break;\r
b18e7050 2080\r
3a4e7a3e
ED
2081 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
2082 DiscardFormIsRequired = TRUE;\r
7c6c064c 2083 SettingLevel = FormLevel;\r
3a4e7a3e
ED
2084 NeedExit = TRUE;\r
2085 break;\r
b18e7050 2086\r
3a4e7a3e
ED
2087 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
2088 SubmitFormIsRequired = TRUE;\r
2089 SettingLevel = FormLevel;\r
2090 break;\r
b18e7050 2091\r
3a4e7a3e
ED
2092 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
2093 DiscardFormIsRequired = TRUE;\r
2094 SettingLevel = FormLevel;\r
2095 break;\r
b18e7050 2096\r
f2e7732e
ED
2097 case EFI_BROWSER_ACTION_REQUEST_RECONNECT:\r
2098 gCallbackReconnect = TRUE;\r
2099 break;\r
2100\r
3a4e7a3e
ED
2101 default:\r
2102 break;\r
2103 }\r
bfae1330 2104 break;\r
061d5462 2105\r
bfae1330
ED
2106 case EFI_BROWSER_ACTION_CHANGING:\r
2107 //\r
2108 // Do the question validation.\r
2109 //\r
2110 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2111 if (!EFI_ERROR (Status)) {\r
e6557276
DB
2112 //\r
2113 //check whether the question value changed compared with edit buffer before updating edit buffer\r
2114 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
2115 //\r
2116 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
bfae1330
ED
2117 //\r
2118 // According the spec, return value from call back of "changing" and \r
2119 // "retrieve" should update to the question's temp buffer.\r
2120 //\r
2121 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
061d5462 2122 }\r
bfae1330 2123 break;\r
061d5462 2124\r
bfae1330
ED
2125 case EFI_BROWSER_ACTION_RETRIEVE:\r
2126 //\r
2127 // According the spec, return value from call back of "changing" and \r
2128 // "retrieve" should update to the question's temp buffer.\r
2129 //\r
798e4d22 2130 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
bfae1330
ED
2131 break;\r
2132\r
2133 default:\r
2134 break;\r
8ca6180f 2135 }\r
c4042207 2136 } else {\r
e6cc2ab3
ED
2137 //\r
2138 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2139 // then the browser will use the value passed to Callback() and ignore the \r
2140 // value returned by Callback(). \r
2141 //\r
2142 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2143 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2144 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2145 } else {\r
2146 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2147 }\r
bfae1330
ED
2148 \r
2149 //\r
2150 // Do the question validation.\r
2151 //\r
fc2e7502
ED
2152 InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2153 if (!EFI_ERROR (InternalStatus)) {\r
e6557276
DB
2154 //\r
2155 //check whether the question value changed compared with edit buffer before updating edit buffer\r
2156 // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
2157 //\r
2158 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
bfae1330
ED
2159 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
2160 }\r
e6cc2ab3
ED
2161 }\r
2162\r
b18e7050 2163 //\r
c4042207
ED
2164 // According the spec, return fail from call back of "changing" and \r
2165 // "retrieve", should restore the question's value.\r
b18e7050 2166 //\r
c792e5b8
ED
2167 if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) {\r
2168 if (Statement->Storage != NULL) {\r
2169 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
2170 } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2171 ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
2172 }\r
2173 }\r
2174\r
2175 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2176 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2177 }\r
2178\r
2179 if (Status == EFI_UNSUPPORTED) {\r
2180 //\r
2181 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2182 //\r
2183 Status = EFI_SUCCESS;\r
2184 }\r
b18e7050 2185 }\r
e6cc2ab3
ED
2186\r
2187 if (BackUpBuffer != NULL) {\r
2188 FreePool (BackUpBuffer);\r
2189 }\r
93551a01
ED
2190\r
2191 //\r
2192 // If Question != NULL, means just process one question\r
2193 // and if code reach here means this question has finished\r
2194 // processing, so just break.\r
2195 //\r
2196 if (Question != NULL) {\r
2197 break;\r
2198 }\r
b18e7050
ED
2199 }\r
2200\r
f2e7732e
ED
2201 if (gCallbackReconnect && (EFI_BROWSER_ACTION_CHANGED == Action)) {\r
2202 //\r
2203 // Confirm changes with user first.\r
2204 //\r
2205 if (IsNvUpdateRequiredForFormSet(FormSet)) {\r
2206 if (BROWSER_ACTION_DISCARD == PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES, NULL, NULL, NULL)) {\r
2207 gCallbackReconnect = FALSE;\r
2208 DiscardFormIsRequired = TRUE;\r
2209 } else {\r
2210 SubmitFormIsRequired = TRUE;\r
2211 }\r
2212 } else {\r
2213 PopupErrorMessage(BROWSER_RECONNECT_REQUIRED, NULL, NULL, NULL);\r
2214 }\r
2215\r
2216 //\r
2217 // Exit current formset before do the reconnect.\r
2218 //\r
2219 NeedExit = TRUE;\r
2220 SettingLevel = FormSetLevel;\r
2221 }\r
2222\r
b18e7050 2223 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2224 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2225 }\r
2226\r
2227 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2228 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2229 }\r
2230\r
2231 if (NeedExit) {\r
7c6c064c 2232 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2233 }\r
2234\r
2235 return Status;\r
2236}\r
2237\r
9776099f
ED
2238/**\r
2239 Call the retrieve type call back function for one question to get the initialize data.\r
2240 \r
2241 This function only used when in the initialize stage, because in this stage, the \r
2242 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2243\r
2244 @param ConfigAccess The config access protocol produced by the hii driver.\r
2245 @param Statement The Question which need to call.\r
061d5462 2246 @param FormSet The formset this question belong to.\r
9776099f
ED
2247\r
2248 @retval EFI_SUCCESS The call back function excutes successfully.\r
2249 @return Other value if the call back function failed to excute. \r
2250**/\r
2251EFI_STATUS \r
2252ProcessRetrieveForQuestion (\r
2253 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
061d5462
ED
2254 IN FORM_BROWSER_STATEMENT *Statement,\r
2255 IN FORM_BROWSER_FORMSET *FormSet\r
9776099f
ED
2256 )\r
2257{\r
2258 EFI_STATUS Status;\r
2259 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2260 EFI_HII_VALUE *HiiValue;\r
2261 EFI_IFR_TYPE_VALUE *TypeValue;\r
061d5462 2262 CHAR16 *NewString;\r
9776099f
ED
2263\r
2264 Status = EFI_SUCCESS;\r
2265 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
70f1d5e7
ED
2266\r
2267 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
9776099f
ED
2268 return EFI_UNSUPPORTED;\r
2269 }\r
2270\r
2271 HiiValue = &Statement->HiiValue;\r
2272 TypeValue = &HiiValue->Value;\r
2273 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2274 //\r
2275 // For OrderedList, passing in the value buffer to Callback()\r
2276 //\r
2277 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2278 }\r
2279 \r
2280 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2281 Status = ConfigAccess->Callback (\r
2282 ConfigAccess,\r
2283 EFI_BROWSER_ACTION_RETRIEVE,\r
2284 Statement->QuestionId,\r
2285 HiiValue->Type,\r
2286 TypeValue,\r
2287 &ActionRequest\r
2288 );\r
061d5462
ED
2289 if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2290 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2291 ASSERT (NewString != NULL);\r
2292\r
2293 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2294 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2295 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2296 } else {\r
2297 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2298 }\r
2299 FreePool (NewString);\r
2300 }\r
2301\r
9776099f
ED
2302 return Status;\r
2303}\r
2304\r
7936fb6a 2305/**\r
2306 The worker function that send the displays to the screen. On output,\r
2307 the selection made by user is returned.\r
2308\r
2309 @param Selection On input, Selection tell setup browser the information\r
2310 about the Selection, form and formset to be displayed.\r
2311 On output, Selection return the screen item that is selected\r
2312 by user.\r
2313\r
2314 @retval EFI_SUCCESS The page is displayed successfully.\r
2315 @return Other value if the page failed to be diplayed.\r
2316\r
2317**/\r
2318EFI_STATUS\r
2319SetupBrowser (\r
2320 IN OUT UI_MENU_SELECTION *Selection\r
2321 )\r
2322{\r
2323 EFI_STATUS Status;\r
2324 LIST_ENTRY *Link;\r
7936fb6a 2325 EFI_HANDLE NotifyHandle;\r
7936fb6a 2326 FORM_BROWSER_STATEMENT *Statement;\r
2327 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2328\r
5adb8db7 2329 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2330\r
2331 //\r
2332 // Register notify for Form package update\r
2333 //\r
2334 Status = mHiiDatabase->RegisterPackageNotify (\r
2335 mHiiDatabase,\r
8d00a0f1 2336 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2337 NULL,\r
2338 FormUpdateNotify,\r
2339 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2340 &NotifyHandle\r
2341 );\r
2342 if (EFI_ERROR (Status)) {\r
2343 return Status;\r
2344 }\r
2345\r
d66e6c16 2346 //\r
2347 // Initialize current settings of Questions in this FormSet\r
2348 //\r
7c6c064c 2349 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2350\r
2351 //\r
7c6c064c 2352 // Initilize Action field.\r
b9feb4bd 2353 //\r
7c6c064c
ED
2354 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2355\r
2356 //\r
2357 // Clean the mCurFakeQestId value is formset refreshed.\r
2358 //\r
2359 mCurFakeQestId = 0;\r
48a9d5f7 2360\r
7936fb6a 2361 do {\r
54f8fc6d
ED
2362 //\r
2363 // IFR is updated, force to reparse the IFR binary\r
93551a01
ED
2364 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and \r
2365 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
54f8fc6d
ED
2366 //\r
2367 if (mHiiPackageListUpdated) {\r
2368 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2369 mHiiPackageListUpdated = FALSE;\r
2370 break;\r
2371 }\r
2372\r
7936fb6a 2373 //\r
2374 // Initialize Selection->Form\r
2375 //\r
2376 if (Selection->FormId == 0) {\r
2377 //\r
2378 // Zero FormId indicates display the first Form in a FormSet\r
2379 //\r
2380 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2381\r
2382 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2383 Selection->FormId = Selection->Form->FormId;\r
2384 } else {\r
2385 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2386 }\r
2387\r
0a1147ed
LG
2388 if (Selection->Form == NULL) {\r
2389 //\r
2390 // No Form to display\r
2391 //\r
13ad1def
LG
2392 Status = EFI_NOT_FOUND;\r
2393 goto Done;\r
0a1147ed
LG
2394 }\r
2395\r
0c66bc76
LG
2396 //\r
2397 // Check Form is suppressed.\r
2398 //\r
2399 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2400 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2401 //\r
2402 // Form is suppressed. \r
2403 //\r
4d4deaac 2404 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
13ad1def
LG
2405 Status = EFI_NOT_FOUND;\r
2406 goto Done;\r
0c66bc76
LG
2407 }\r
2408 }\r
5adb8db7 2409\r
5adb8db7
LG
2410 //\r
2411 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2412 // for each question with callback flag.\r
2413 // New form may be the first form, or the different form after another form close.\r
2414 //\r
70f1d5e7 2415 if (((Selection->Handle != mCurrentHiiHandle) ||\r
13ad1def
LG
2416 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2417 (Selection->FormId != mCurrentFormId))) {\r
6fd184d0
ED
2418 //\r
2419 // Update Retrieve flag.\r
2420 //\r
2421 mFinishRetrieveCall = FALSE;\r
2422\r
13ad1def
LG
2423 //\r
2424 // Keep current form information\r
2425 //\r
2426 mCurrentHiiHandle = Selection->Handle;\r
2427 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2428 mCurrentFormId = Selection->FormId;\r
2429\r
70f1d5e7 2430 if (ConfigAccess != NULL) {\r
6fd184d0 2431 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
70f1d5e7
ED
2432 if (EFI_ERROR (Status)) {\r
2433 goto Done;\r
2434 }\r
b18e7050 2435\r
70f1d5e7 2436 //\r
93551a01 2437 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
70f1d5e7
ED
2438 //\r
2439 if (mHiiPackageListUpdated) {\r
2440 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2441 mHiiPackageListUpdated = FALSE;\r
2442 break;\r
2443 }\r
5adb8db7
LG
2444 }\r
2445 }\r
2446\r
7936fb6a 2447 //\r
2448 // Load Questions' Value for display\r
2449 //\r
eccfeab1 2450 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2451 if (EFI_ERROR (Status)) {\r
13ad1def 2452 goto Done;\r
7936fb6a 2453 }\r
2454\r
6fd184d0
ED
2455 if (!mFinishRetrieveCall) {\r
2456 //\r
2457 // Finish call RETRIEVE callback for this form.\r
2458 //\r
2459 mFinishRetrieveCall = TRUE;\r
798e4d22 2460\r
6fd184d0
ED
2461 if (ConfigAccess != NULL) {\r
2462 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
2463 if (EFI_ERROR (Status)) {\r
2464 goto Done;\r
2465 }\r
2466\r
2467 //\r
2468 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2469 //\r
2470 if (mHiiPackageListUpdated) {\r
2471 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2472 mHiiPackageListUpdated = FALSE;\r
2473 break;\r
2474 }\r
2475 }\r
eccfeab1
LG
2476 }\r
2477\r
7936fb6a 2478 //\r
2479 // Display form\r
2480 //\r
7c6c064c 2481 Status = DisplayForm ();\r
7936fb6a 2482 if (EFI_ERROR (Status)) {\r
13ad1def 2483 goto Done;\r
7936fb6a 2484 }\r
2485\r
2486 //\r
2487 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2488 //\r
2489 Statement = Selection->Statement;\r
2490 if (Statement != NULL) {\r
13ad1def
LG
2491 if ((ConfigAccess != NULL) && \r
2492 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2493 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2494 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2495 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2496 //\r
2497 // Process dynamic update ref opcode.\r
2498 //\r
2499 if (!EFI_ERROR (Status)) {\r
7c6c064c 2500 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2501 }\r
2502 \r
3dde743f 2503 //\r
8ca6180f 2504 // Callback return error status or status return from process goto opcode.\r
3dde743f 2505 //\r
8ca6180f 2506 if (EFI_ERROR (Status)) {\r
3dde743f 2507 //\r
2508 // Cross reference will not be taken\r
2509 //\r
2510 Selection->FormId = Selection->Form->FormId;\r
2511 Selection->QuestionId = 0;\r
2512 }\r
7936fb6a 2513 }\r
b7891584 2514\r
a6c0ad81 2515\r
ca2be854
ED
2516 if (!EFI_ERROR (Status) && \r
2517 (Statement->Operand != EFI_IFR_REF_OP) && \r
2518 ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
2519 //\r
2520 // Only question value has been changed, browser will trig CHANGED callback.\r
2521 //\r
798e4d22 2522 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
e6557276
DB
2523 //\r
2524 //check whether the question value changed compared with buffer value\r
2525 //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen\r
2526 //\r
2527 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
b7891584 2528 }\r
bfae1330 2529 } else {\r
a6c0ad81 2530 //\r
bfae1330 2531 // Do the question validation.\r
a6c0ad81 2532 //\r
bfae1330
ED
2533 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2534 if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
2535 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
2536 //\r
2537 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2538 //\r
2539 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2540 }\r
7936fb6a 2541 }\r
892eccc8 2542\r
b1239a24 2543 //\r
f2e7732e
ED
2544 // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage \r
2545 // and process question success till here, trig the gResetFlag/gFlagReconnect.\r
b1239a24
ED
2546 //\r
2547 if ((Status == EFI_SUCCESS) && \r
f2e7732e
ED
2548 (Statement->Storage == NULL)) { \r
2549 if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
2550 gResetRequired = TRUE;\r
2551 }\r
2552\r
2553 if ((Statement->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
2554 gFlagReconnect = TRUE;\r
2555 }\r
b1239a24 2556 }\r
7936fb6a 2557 }\r
7936fb6a 2558\r
7c6c064c
ED
2559 //\r
2560 // Check whether Exit flag is TRUE.\r
2561 //\r
2562 if (gExitRequired) {\r
2563 switch (gBrowserSettingScope) {\r
2564 case SystemLevel:\r
2565 Selection->Action = UI_ACTION_EXIT;\r
2566 break;\r
2567\r
2568 case FormSetLevel:\r
2569 case FormLevel:\r
2570 FindNextMenu (Selection, gBrowserSettingScope);\r
2571 break;\r
2572\r
2573 default:\r
2574 break;\r
2575 }\r
2576\r
2577 gExitRequired = FALSE;\r
2578 }\r
2579\r
5adb8db7
LG
2580 //\r
2581 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2582 // for each question with callback flag.\r
2583 //\r
5adb8db7
LG
2584 if ((ConfigAccess != NULL) && \r
2585 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2586 (Selection->Handle != mCurrentHiiHandle) ||\r
2587 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2588 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2589\r
798e4d22 2590 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2591 if (EFI_ERROR (Status)) {\r
2592 goto Done;\r
f4a2af1f 2593 }\r
2594 }\r
5adb8db7 2595 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2596\r
d66e6c16 2597Done:\r
13ad1def
LG
2598 //\r
2599 // Reset current form information to the initial setting when error happens or form exit.\r
2600 //\r
2601 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2602 mCurrentHiiHandle = NULL;\r
2603 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2604 mCurrentFormId = 0;\r
2605 }\r
2606\r
7936fb6a 2607 //\r
2608 // Unregister notify for Form package update\r
2609 //\r
13ad1def
LG
2610 mHiiDatabase->UnregisterPackageNotify (\r
2611 mHiiDatabase,\r
2612 NotifyHandle\r
2613 );\r
7936fb6a 2614 return Status;\r
2615}\r