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