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