]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg: Refine the get default value logic.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for UI presentation.\r
3\r
892eccc8 4Copyright (c) 2004 - 2014, 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
ED
1447 @param UserInput The user input data.\r
1448 @param ChangeHighlight Whether need to change the highlight statement. \r
d66e6c16 1449\r
7936fb6a 1450 @retval EFI_SUCESSS This function always return successfully for now.\r
1451\r
1452**/\r
1453EFI_STATUS\r
7c6c064c
ED
1454ProcessUserInput (\r
1455 IN USER_INPUT *UserInput,\r
1456 IN BOOLEAN ChangeHighlight\r
7936fb6a 1457 )\r
1458{\r
7c6c064c
ED
1459 EFI_STATUS Status;\r
1460 FORM_BROWSER_STATEMENT *Statement;\r
25361615 1461\r
7c6c064c 1462 Status = EFI_SUCCESS;\r
7936fb6a 1463\r
1464 //\r
7c6c064c 1465 // When Exit from FormDisplay function, one of the below two cases must be true.\r
7936fb6a 1466 //\r
7c6c064c 1467 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
7936fb6a 1468\r
b9feb4bd 1469 //\r
7c6c064c 1470 // Remove the last highligh question id, this id will update when show next form.\r
b9feb4bd 1471 //\r
7c6c064c 1472 gCurrentSelection->QuestionId = 0;\r
7936fb6a 1473\r
7c6c064c
ED
1474 //\r
1475 // First process the Action field in USER_INPUT.\r
1476 //\r
1477 if (UserInput->Action != 0) {\r
1478 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
1479 if (EFI_ERROR (Status)) {\r
1480 return Status;\r
1481 }\r
7936fb6a 1482\r
7c6c064c
ED
1483 //\r
1484 // Clear the highlight info.\r
1485 //\r
1486 gCurrentSelection->Statement = NULL;\r
7936fb6a 1487\r
7c6c064c
ED
1488 if (UserInput->SelectedStatement != NULL) {\r
1489 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1490 ASSERT (Statement != NULL);\r
1491 //\r
1492 // Save the current highlight menu in the menu history data.\r
1493 // which will be used when later browse back to this form.\r
1494 //\r
1495 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1496 //\r
1497 // For statement like text, actio, it not has question id.\r
1498 // So use FakeQuestionId to save the question.\r
1499 //\r
1500 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1501 mCurFakeQestId = Statement->FakeQuestionId;\r
1502 } else {\r
1503 mCurFakeQestId = 0;\r
1504 }\r
1505 }\r
1506 } else {\r
1507 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1508 ASSERT (Statement != NULL);\r
7936fb6a 1509\r
7c6c064c 1510 gCurrentSelection->Statement = Statement;\r
25361615 1511\r
7c6c064c
ED
1512 if (ChangeHighlight) {\r
1513 //\r
1514 // This question is the current user select one,record it and later\r
1515 // show it as the highlight question.\r
1516 //\r
1517 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1518 //\r
1519 // For statement like text, actio, it not has question id.\r
1520 // So use FakeQuestionId to save the question.\r
1521 //\r
1522 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1523 mCurFakeQestId = Statement->FakeQuestionId;\r
1524 } else {\r
1525 mCurFakeQestId = 0;\r
7936fb6a 1526 }\r
7c6c064c 1527 }\r
7936fb6a 1528\r
7c6c064c
ED
1529 switch (Statement->Operand) {\r
1530 case EFI_IFR_REF_OP:\r
1531 Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
1532 break;\r
1533 \r
1534 case EFI_IFR_ACTION_OP:\r
1535 //\r
1536 // Process the Config string <ConfigResp>\r
1537 //\r
1538 Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
1539 break;\r
1540 \r
1541 case EFI_IFR_RESET_BUTTON_OP:\r
7936fb6a 1542 //\r
7c6c064c 1543 // Reset Question to default value specified by DefaultId\r
7936fb6a 1544 //\r
787fc2a6 1545 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
892eccc8 1546 UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
7c6c064c
ED
1547 break;\r
1548\r
1549 default:\r
1550 switch (Statement->Operand) {\r
1551 case EFI_IFR_STRING_OP:\r
1552 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1553 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1554 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1555 FreePool (UserInput->InputValue.Buffer);\r
1556 break;\r
1557\r
1558 case EFI_IFR_PASSWORD_OP:\r
1559 if (UserInput->InputValue.Buffer == NULL) {\r
1560 //\r
1561 // User not input new password, just return.\r
1562 //\r
1563 break;\r
1564 }\r
8b0fc5c1 1565\r
7c6c064c
ED
1566 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1567 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1568 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1569 FreePool (UserInput->InputValue.Buffer);\r
8b0fc5c1 1570 //\r
7c6c064c 1571 // Two password match, send it to Configuration Driver\r
8b0fc5c1 1572 //\r
7c6c064c
ED
1573 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
1574 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
1575 //\r
1576 // Clean the value after saved it.\r
1577 //\r
1578 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
1579 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
1580 } else {\r
1581 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
1582 }\r
1583 break;\r
1584\r
1585 case EFI_IFR_ORDERED_LIST_OP:\r
1586 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
1587 break;\r
1588\r
1589 default:\r
1590 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
1591 break;\r
1592 }\r
7c6c064c 1593 break;\r
7936fb6a 1594 }\r
7936fb6a 1595 }\r
1596\r
7936fb6a 1597 return Status;\r
1598}\r
1599\r
1600/**\r
7936fb6a 1601\r
7c6c064c 1602 Display form and wait for user to select one menu option, then return it.\r
7936fb6a 1603\r
7c6c064c 1604 @retval EFI_SUCESSS This function always return successfully for now.\r
48a9d5f7
LG
1605\r
1606**/\r
7c6c064c
ED
1607EFI_STATUS\r
1608DisplayForm (\r
48a9d5f7
LG
1609 VOID\r
1610 )\r
1611{\r
7c6c064c
ED
1612 EFI_STATUS Status;\r
1613 USER_INPUT UserInput;\r
1614 FORM_ENTRY_INFO *CurrentMenu;\r
1615 BOOLEAN ChangeHighlight;\r
48a9d5f7 1616\r
7c6c064c 1617 ZeroMem (&UserInput, sizeof (USER_INPUT));\r
48a9d5f7
LG
1618\r
1619 //\r
7c6c064c 1620 // Update the menu history data.\r
48a9d5f7 1621 //\r
7c6c064c
ED
1622 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
1623 if (CurrentMenu == NULL) {\r
48a9d5f7 1624 //\r
7c6c064c 1625 // Current menu not found, add it to the menu tree\r
25361615 1626 //\r
7c6c064c
ED
1627 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
1628 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
1629 ASSERT (CurrentMenu != NULL);\r
1630 }\r
4d4deaac
ED
1631\r
1632 //\r
1633 // Back up the form view history data for this form.\r
1634 //\r
1635 UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
1636\r
7c6c064c 1637 gCurrentSelection->CurrentMenu = CurrentMenu;\r
48a9d5f7 1638\r
7c6c064c
ED
1639 //\r
1640 // Find currrent highlight statement.\r
1641 //\r
1642 if (gCurrentSelection->QuestionId == 0) {\r
48a9d5f7 1643 //\r
7c6c064c 1644 // Highlight not specified, fetch it from cached menu\r
48a9d5f7 1645 //\r
7c6c064c 1646 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
48a9d5f7 1647 }\r
25361615 1648\r
7c6c064c
ED
1649 //\r
1650 // Evaluate all the Expressions in this Form\r
1651 //\r
1652 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
1653 if (EFI_ERROR (Status)) {\r
1654 return Status;\r
b9feb4bd 1655 }\r
7936fb6a 1656\r
7c6c064c 1657 UpdateDisplayFormData ();\r
25361615 1658\r
7c6c064c
ED
1659 //\r
1660 // Three possible status maybe return.\r
1661 //\r
1662 // EFI_INVALID_PARAMETER: The input dimension info is not valid.\r
1663 // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid\r
1664 // and an valid value has return.\r
1665 // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.\r
1666 //\r
4d4deaac 1667 ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
7c6c064c
ED
1668 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
1669 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
1670 FreeDisplayFormData();\r
1671 return Status;\r
1672 }\r
25361615 1673\r
7c6c064c
ED
1674 //\r
1675 // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.\r
1676 // in this case, browser need to change the highlight menu.\r
1677 // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist \r
1678 // opcode and new valid value has return, browser core need to adjust\r
1679 // value for this opcode and shows this form again.\r
1680 //\r
1681 ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);\r
25361615 1682\r
7c6c064c 1683 Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
25361615 1684\r
7c6c064c 1685 FreeDisplayFormData();\r
25361615 1686\r
7c6c064c 1687 return Status;\r
7936fb6a 1688}\r
1689\r
1690/**\r
1691 Functions which are registered to receive notification of\r
1692 database events have this prototype. The actual event is encoded\r
1693 in NotifyType. The following table describes how PackageType,\r
1694 PackageGuid, Handle, and Package are used for each of the\r
1695 notification types.\r
1696\r
1697 @param PackageType Package type of the notification.\r
1698\r
1699 @param PackageGuid If PackageType is\r
1700 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
1701 the pointer to the GUID from the Guid\r
1702 field of EFI_HII_PACKAGE_GUID_HEADER.\r
1703 Otherwise, it must be NULL.\r
1704\r
1705 @param Package Points to the package referred to by the\r
1706 notification Handle The handle of the package\r
1707 list which contains the specified package.\r
1708\r
1709 @param Handle The HII handle.\r
1710\r
1711 @param NotifyType The type of change concerning the\r
1712 database. See\r
1713 EFI_HII_DATABASE_NOTIFY_TYPE.\r
1714\r
1715**/\r
1716EFI_STATUS\r
6d3ea23f 1717EFIAPI\r
7936fb6a 1718FormUpdateNotify (\r
1719 IN UINT8 PackageType,\r
1720 IN CONST EFI_GUID *PackageGuid,\r
1721 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
1722 IN EFI_HII_HANDLE Handle,\r
1723 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
1724 )\r
1725{\r
1726 mHiiPackageListUpdated = TRUE;\r
1727\r
1728 return EFI_SUCCESS;\r
1729}\r
1730\r
b18e7050 1731/**\r
7c6c064c 1732 Update the NV flag info for this form set.\r
b18e7050
ED
1733\r
1734 @param FormSet FormSet data structure.\r
1735\r
b18e7050 1736**/\r
7c6c064c
ED
1737BOOLEAN\r
1738IsNvUpdateRequiredForFormSet (\r
b18e7050
ED
1739 IN FORM_BROWSER_FORMSET *FormSet\r
1740 )\r
1741{\r
1742 LIST_ENTRY *Link;\r
1743 FORM_BROWSER_FORM *Form;\r
7c6c064c
ED
1744 BOOLEAN RetVal;\r
1745\r
1746 //\r
1747 // Not finished question initialization, return FALSE.\r
1748 //\r
1749 if (!FormSet->QuestionInited) {\r
1750 return FALSE;\r
1751 }\r
1752\r
1753 RetVal = FALSE;\r
b18e7050
ED
1754\r
1755 Link = GetFirstNode (&FormSet->FormListHead);\r
1756 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1757 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1758\r
7c6c064c
ED
1759 RetVal = IsNvUpdateRequiredForForm(Form);\r
1760 if (RetVal) {\r
1761 break;\r
b9feb4bd
ED
1762 }\r
1763\r
25361615 1764 Link = GetNextNode (&FormSet->FormListHead, Link);\r
b9feb4bd
ED
1765 }\r
1766\r
7c6c064c
ED
1767 return RetVal;\r
1768}\r
1769\r
1770/**\r
1771 Update the NvUpdateRequired flag for a form.\r
1772\r
1773 @param Form Form data structure.\r
1774\r
1775**/\r
1776BOOLEAN\r
1777IsNvUpdateRequiredForForm (\r
1778 IN FORM_BROWSER_FORM *Form\r
1779 )\r
1780{\r
1781 LIST_ENTRY *Link;\r
1782 FORM_BROWSER_STATEMENT *Statement;\r
1783\r
1784 Link = GetFirstNode (&Form->StatementListHead);\r
1785 while (!IsNull (&Form->StatementListHead, Link)) {\r
1786 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1787\r
1788 if (Statement->ValueChanged) {\r
1789 return TRUE;\r
1790 }\r
1791\r
1792 Link = GetNextNode (&Form->StatementListHead, Link);\r
1793 }\r
1794\r
b18e7050
ED
1795 return FALSE;\r
1796}\r
1797\r
b18e7050
ED
1798/**\r
1799 Find menu which will show next time.\r
1800\r
1801 @param Selection On input, Selection tell setup browser the information\r
1802 about the Selection, form and formset to be displayed.\r
1803 On output, Selection return the screen item that is selected\r
1804 by user.\r
7c6c064c
ED
1805 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
1806 else, we need to exit current formset.\r
b18e7050 1807 \r
7c6c064c
ED
1808 @retval TRUE Exit current form.\r
1809 @retval FALSE User press ESC and keep in current form.\r
b18e7050
ED
1810**/\r
1811BOOLEAN\r
1812FindNextMenu (\r
7c6c064c 1813 IN OUT UI_MENU_SELECTION *Selection,\r
93551a01 1814 IN BROWSER_SETTING_SCOPE SettingLevel\r
b18e7050
ED
1815 )\r
1816{\r
7c6c064c
ED
1817 FORM_ENTRY_INFO *CurrentMenu;\r
1818 FORM_ENTRY_INFO *ParentMenu;\r
1819 BROWSER_SETTING_SCOPE Scope;\r
b18e7050
ED
1820 \r
1821 CurrentMenu = Selection->CurrentMenu;\r
7c6c064c 1822 Scope = FormSetLevel;\r
b18e7050 1823\r
93551a01
ED
1824 ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
1825 while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
1826 ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
1827 }\r
25361615 1828\r
93551a01
ED
1829 if (ParentMenu != NULL) {\r
1830 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1831 Scope = FormLevel;\r
7c6c064c
ED
1832 } else {\r
1833 Scope = FormSetLevel;\r
b18e7050 1834 }\r
25361615
ED
1835 }\r
1836\r
b9feb4bd 1837 //\r
7c6c064c 1838 // Form Level Check whether the data is changed.\r
b9feb4bd 1839 //\r
7c6c064c
ED
1840 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
1841 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
4d4deaac 1842 if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
25361615
ED
1843 return FALSE;\r
1844 }\r
7c6c064c 1845 }\r
b9feb4bd 1846\r
7c6c064c
ED
1847 if (ParentMenu != NULL) {\r
1848 //\r
1849 // ParentMenu is found. Then, go to it.\r
1850 //\r
1851 if (Scope == FormLevel) {\r
1852 Selection->Action = UI_ACTION_REFRESH_FORM;\r
25361615 1853 } else {\r
7c6c064c
ED
1854 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1855 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
1856 Selection->Handle = ParentMenu->HiiHandle;\r
25361615 1857 }\r
25361615 1858\r
7c6c064c
ED
1859 Selection->Statement = NULL;\r
1860\r
1861 Selection->FormId = ParentMenu->FormId;\r
1862 Selection->QuestionId = ParentMenu->QuestionId;\r
1863\r
1864 //\r
1865 // Clear highlight record for this menu\r
1866 //\r
25361615 1867 CurrentMenu->QuestionId = 0;\r
7c6c064c 1868 return FALSE;\r
25361615
ED
1869 }\r
1870\r
7c6c064c
ED
1871 //\r
1872 // Current in root page, exit the SendForm\r
1873 //\r
25361615 1874 Selection->Action = UI_ACTION_EXIT;\r
7c6c064c 1875\r
b18e7050
ED
1876 return TRUE;\r
1877}\r
1878\r
1879/**\r
1880 Call the call back function for the question and process the return action.\r
1881\r
1882 @param Selection On input, Selection tell setup browser the information\r
1883 about the Selection, form and formset to be displayed.\r
1884 On output, Selection return the screen item that is selected\r
1885 by user.\r
798e4d22
ED
1886 @param FormSet The formset this question belong to.\r
1887 @param Form The form this question belong to.\r
b18e7050
ED
1888 @param Question The Question which need to call.\r
1889 @param Action The action request.\r
1890 @param SkipSaveOrDiscard Whether skip save or discard action.\r
1891\r
1892 @retval EFI_SUCCESS The call back function excutes successfully.\r
1893 @return Other value if the call back function failed to excute. \r
1894**/\r
1895EFI_STATUS \r
1896ProcessCallBackFunction (\r
1897 IN OUT UI_MENU_SELECTION *Selection,\r
798e4d22
ED
1898 IN FORM_BROWSER_FORMSET *FormSet,\r
1899 IN FORM_BROWSER_FORM *Form,\r
b18e7050
ED
1900 IN FORM_BROWSER_STATEMENT *Question,\r
1901 IN EFI_BROWSER_ACTION Action,\r
1902 IN BOOLEAN SkipSaveOrDiscard\r
1903 )\r
1904{\r
1905 EFI_STATUS Status;\r
1906 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
1907 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1908 EFI_HII_VALUE *HiiValue;\r
1909 EFI_IFR_TYPE_VALUE *TypeValue;\r
1910 FORM_BROWSER_STATEMENT *Statement;\r
1911 BOOLEAN SubmitFormIsRequired;\r
b18e7050
ED
1912 BOOLEAN DiscardFormIsRequired;\r
1913 BOOLEAN NeedExit;\r
1914 LIST_ENTRY *Link;\r
48a9d5f7 1915 BROWSER_SETTING_SCOPE SettingLevel;\r
e6cc2ab3
ED
1916 EFI_IFR_TYPE_VALUE BackUpValue;\r
1917 UINT8 *BackUpBuffer;\r
061d5462 1918 CHAR16 *NewString;\r
b18e7050 1919\r
798e4d22 1920 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 1921 SubmitFormIsRequired = FALSE;\r
48a9d5f7 1922 SettingLevel = FormSetLevel;\r
b18e7050
ED
1923 DiscardFormIsRequired = FALSE;\r
1924 NeedExit = FALSE;\r
1925 Status = EFI_SUCCESS;\r
1926 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 1927 BackUpBuffer = NULL;\r
b18e7050
ED
1928\r
1929 if (ConfigAccess == NULL) {\r
1930 return EFI_SUCCESS;\r
1931 }\r
1932\r
798e4d22
ED
1933 Link = GetFirstNode (&Form->StatementListHead);\r
1934 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 1935 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 1936 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
1937\r
1938 //\r
1939 // if Question != NULL, only process the question. Else, process all question in this form.\r
1940 //\r
1941 if ((Question != NULL) && (Statement != Question)) {\r
1942 continue;\r
1943 }\r
1944 \r
1945 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
1946 continue;\r
1947 }\r
1948\r
1949 //\r
1950 // Check whether Statement is disabled.\r
1951 //\r
31585af4 1952 if (Statement->Expression != NULL) {\r
798e4d22 1953 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
1954 continue;\r
1955 }\r
1956 }\r
1957\r
1958 HiiValue = &Statement->HiiValue;\r
1959 TypeValue = &HiiValue->Value;\r
1960 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
1961 //\r
1962 // For OrderedList, passing in the value buffer to Callback()\r
1963 //\r
1964 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
1965 }\r
e6cc2ab3
ED
1966\r
1967 //\r
1968 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
1969 //\r
1970 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
1971 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
1972 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
523f48e7 1973 ASSERT (BackUpBuffer != NULL);\r
e6cc2ab3
ED
1974 } else {\r
1975 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
1976 }\r
1977 }\r
1978\r
b18e7050
ED
1979 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1980 Status = ConfigAccess->Callback (\r
1981 ConfigAccess,\r
1982 Action,\r
1983 Statement->QuestionId,\r
1984 HiiValue->Type,\r
1985 TypeValue,\r
1986 &ActionRequest\r
1987 );\r
1988 if (!EFI_ERROR (Status)) {\r
bfae1330
ED
1989 //\r
1990 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
1991 //\r
1992 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1993 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
1994 ASSERT (NewString != NULL);\r
1995\r
1996 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
1997 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
1998 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
1999 } else {\r
2000 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2001 }\r
2002 FreePool (NewString);\r
2003 }\r
2004\r
3a4e7a3e
ED
2005 //\r
2006 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
2007 //\r
bfae1330
ED
2008 switch (Action) {\r
2009 case EFI_BROWSER_ACTION_CHANGED:\r
3a4e7a3e
ED
2010 switch (ActionRequest) {\r
2011 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 2012 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 2013 gResetRequired = TRUE;\r
7c6c064c 2014 NeedExit = TRUE;\r
3a4e7a3e 2015 break;\r
b18e7050 2016\r
3a4e7a3e
ED
2017 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2018 SubmitFormIsRequired = TRUE;\r
7c6c064c 2019 NeedExit = TRUE;\r
3a4e7a3e 2020 break;\r
b18e7050 2021\r
3a4e7a3e 2022 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 2023 DiscardFormIsRequired = TRUE;\r
7c6c064c 2024 NeedExit = TRUE;\r
3a4e7a3e 2025 break;\r
b18e7050 2026\r
3a4e7a3e
ED
2027 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
2028 SubmitFormIsRequired = TRUE;\r
2029 SettingLevel = FormLevel;\r
2030 NeedExit = TRUE;\r
2031 break;\r
b18e7050 2032\r
3a4e7a3e
ED
2033 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
2034 DiscardFormIsRequired = TRUE;\r
7c6c064c 2035 SettingLevel = FormLevel;\r
3a4e7a3e
ED
2036 NeedExit = TRUE;\r
2037 break;\r
b18e7050 2038\r
3a4e7a3e
ED
2039 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
2040 SubmitFormIsRequired = TRUE;\r
2041 SettingLevel = FormLevel;\r
2042 break;\r
b18e7050 2043\r
3a4e7a3e
ED
2044 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
2045 DiscardFormIsRequired = TRUE;\r
2046 SettingLevel = FormLevel;\r
2047 break;\r
b18e7050 2048\r
3a4e7a3e
ED
2049 default:\r
2050 break;\r
2051 }\r
bfae1330 2052 break;\r
061d5462 2053\r
bfae1330
ED
2054 case EFI_BROWSER_ACTION_CHANGING:\r
2055 //\r
2056 // Do the question validation.\r
2057 //\r
2058 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2059 if (!EFI_ERROR (Status)) {\r
2060 //\r
2061 // According the spec, return value from call back of "changing" and \r
2062 // "retrieve" should update to the question's temp buffer.\r
2063 //\r
2064 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
061d5462 2065 }\r
bfae1330 2066 break;\r
061d5462 2067\r
bfae1330
ED
2068 case EFI_BROWSER_ACTION_RETRIEVE:\r
2069 //\r
2070 // According the spec, return value from call back of "changing" and \r
2071 // "retrieve" should update to the question's temp buffer.\r
2072 //\r
798e4d22 2073 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
bfae1330
ED
2074 break;\r
2075\r
2076 default:\r
2077 break;\r
8ca6180f 2078 }\r
c4042207 2079 } else {\r
e6cc2ab3
ED
2080 //\r
2081 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2082 // then the browser will use the value passed to Callback() and ignore the \r
2083 // value returned by Callback(). \r
2084 //\r
2085 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2086 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2087 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2088 } else {\r
2089 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2090 }\r
bfae1330
ED
2091 \r
2092 //\r
2093 // Do the question validation.\r
2094 //\r
2095 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2096 if (!EFI_ERROR (Status)) {\r
2097 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
2098 }\r
e6cc2ab3
ED
2099 }\r
2100\r
b18e7050 2101 //\r
c4042207
ED
2102 // According the spec, return fail from call back of "changing" and \r
2103 // "retrieve", should restore the question's value.\r
b18e7050 2104 //\r
e6cc2ab3
ED
2105 if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || \r
2106 Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2107 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2108 }\r
2109\r
2110 if (Status == EFI_UNSUPPORTED) {\r
2111 //\r
2112 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2113 //\r
2114 Status = EFI_SUCCESS;\r
2115 }\r
b18e7050 2116 }\r
e6cc2ab3
ED
2117\r
2118 if (BackUpBuffer != NULL) {\r
2119 FreePool (BackUpBuffer);\r
2120 }\r
93551a01
ED
2121\r
2122 //\r
2123 // If Question != NULL, means just process one question\r
2124 // and if code reach here means this question has finished\r
2125 // processing, so just break.\r
2126 //\r
2127 if (Question != NULL) {\r
2128 break;\r
2129 }\r
b18e7050
ED
2130 }\r
2131\r
2132 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2133 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2134 }\r
2135\r
2136 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2137 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2138 }\r
2139\r
2140 if (NeedExit) {\r
7c6c064c 2141 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2142 }\r
2143\r
2144 return Status;\r
2145}\r
2146\r
9776099f
ED
2147/**\r
2148 Call the retrieve type call back function for one question to get the initialize data.\r
2149 \r
2150 This function only used when in the initialize stage, because in this stage, the \r
2151 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2152\r
2153 @param ConfigAccess The config access protocol produced by the hii driver.\r
2154 @param Statement The Question which need to call.\r
061d5462 2155 @param FormSet The formset this question belong to.\r
9776099f
ED
2156\r
2157 @retval EFI_SUCCESS The call back function excutes successfully.\r
2158 @return Other value if the call back function failed to excute. \r
2159**/\r
2160EFI_STATUS \r
2161ProcessRetrieveForQuestion (\r
2162 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
061d5462
ED
2163 IN FORM_BROWSER_STATEMENT *Statement,\r
2164 IN FORM_BROWSER_FORMSET *FormSet\r
9776099f
ED
2165 )\r
2166{\r
2167 EFI_STATUS Status;\r
2168 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2169 EFI_HII_VALUE *HiiValue;\r
2170 EFI_IFR_TYPE_VALUE *TypeValue;\r
061d5462 2171 CHAR16 *NewString;\r
9776099f
ED
2172\r
2173 Status = EFI_SUCCESS;\r
2174 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
70f1d5e7
ED
2175\r
2176 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
9776099f
ED
2177 return EFI_UNSUPPORTED;\r
2178 }\r
2179\r
2180 HiiValue = &Statement->HiiValue;\r
2181 TypeValue = &HiiValue->Value;\r
2182 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2183 //\r
2184 // For OrderedList, passing in the value buffer to Callback()\r
2185 //\r
2186 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2187 }\r
2188 \r
2189 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2190 Status = ConfigAccess->Callback (\r
2191 ConfigAccess,\r
2192 EFI_BROWSER_ACTION_RETRIEVE,\r
2193 Statement->QuestionId,\r
2194 HiiValue->Type,\r
2195 TypeValue,\r
2196 &ActionRequest\r
2197 );\r
061d5462
ED
2198 if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2199 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2200 ASSERT (NewString != NULL);\r
2201\r
2202 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2203 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2204 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2205 } else {\r
2206 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2207 }\r
2208 FreePool (NewString);\r
2209 }\r
2210\r
9776099f
ED
2211 return Status;\r
2212}\r
2213\r
7936fb6a 2214/**\r
2215 The worker function that send the displays to the screen. On output,\r
2216 the selection made by user is returned.\r
2217\r
2218 @param Selection On input, Selection tell setup browser the information\r
2219 about the Selection, form and formset to be displayed.\r
2220 On output, Selection return the screen item that is selected\r
2221 by user.\r
2222\r
2223 @retval EFI_SUCCESS The page is displayed successfully.\r
2224 @return Other value if the page failed to be diplayed.\r
2225\r
2226**/\r
2227EFI_STATUS\r
2228SetupBrowser (\r
2229 IN OUT UI_MENU_SELECTION *Selection\r
2230 )\r
2231{\r
2232 EFI_STATUS Status;\r
2233 LIST_ENTRY *Link;\r
7936fb6a 2234 EFI_HANDLE NotifyHandle;\r
7936fb6a 2235 FORM_BROWSER_STATEMENT *Statement;\r
2236 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2237\r
5adb8db7 2238 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2239\r
2240 //\r
2241 // Register notify for Form package update\r
2242 //\r
2243 Status = mHiiDatabase->RegisterPackageNotify (\r
2244 mHiiDatabase,\r
8d00a0f1 2245 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2246 NULL,\r
2247 FormUpdateNotify,\r
2248 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2249 &NotifyHandle\r
2250 );\r
2251 if (EFI_ERROR (Status)) {\r
2252 return Status;\r
2253 }\r
2254\r
d66e6c16 2255 //\r
2256 // Initialize current settings of Questions in this FormSet\r
2257 //\r
7c6c064c 2258 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2259\r
2260 //\r
7c6c064c 2261 // Initilize Action field.\r
b9feb4bd 2262 //\r
7c6c064c
ED
2263 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2264\r
2265 //\r
2266 // Clean the mCurFakeQestId value is formset refreshed.\r
2267 //\r
2268 mCurFakeQestId = 0;\r
48a9d5f7 2269\r
7936fb6a 2270 do {\r
54f8fc6d
ED
2271 //\r
2272 // IFR is updated, force to reparse the IFR binary\r
93551a01
ED
2273 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and \r
2274 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
54f8fc6d
ED
2275 //\r
2276 if (mHiiPackageListUpdated) {\r
2277 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2278 mHiiPackageListUpdated = FALSE;\r
2279 break;\r
2280 }\r
2281\r
7936fb6a 2282 //\r
2283 // Initialize Selection->Form\r
2284 //\r
2285 if (Selection->FormId == 0) {\r
2286 //\r
2287 // Zero FormId indicates display the first Form in a FormSet\r
2288 //\r
2289 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2290\r
2291 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2292 Selection->FormId = Selection->Form->FormId;\r
2293 } else {\r
2294 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2295 }\r
2296\r
0a1147ed
LG
2297 if (Selection->Form == NULL) {\r
2298 //\r
2299 // No Form to display\r
2300 //\r
13ad1def
LG
2301 Status = EFI_NOT_FOUND;\r
2302 goto Done;\r
0a1147ed
LG
2303 }\r
2304\r
0c66bc76
LG
2305 //\r
2306 // Check Form is suppressed.\r
2307 //\r
2308 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2309 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2310 //\r
2311 // Form is suppressed. \r
2312 //\r
4d4deaac 2313 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
13ad1def
LG
2314 Status = EFI_NOT_FOUND;\r
2315 goto Done;\r
0c66bc76
LG
2316 }\r
2317 }\r
5adb8db7 2318\r
5adb8db7
LG
2319 //\r
2320 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2321 // for each question with callback flag.\r
2322 // New form may be the first form, or the different form after another form close.\r
2323 //\r
70f1d5e7 2324 if (((Selection->Handle != mCurrentHiiHandle) ||\r
13ad1def
LG
2325 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2326 (Selection->FormId != mCurrentFormId))) {\r
6fd184d0
ED
2327 //\r
2328 // Update Retrieve flag.\r
2329 //\r
2330 mFinishRetrieveCall = FALSE;\r
2331\r
13ad1def
LG
2332 //\r
2333 // Keep current form information\r
2334 //\r
2335 mCurrentHiiHandle = Selection->Handle;\r
2336 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2337 mCurrentFormId = Selection->FormId;\r
2338\r
70f1d5e7 2339 if (ConfigAccess != NULL) {\r
6fd184d0 2340 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
70f1d5e7
ED
2341 if (EFI_ERROR (Status)) {\r
2342 goto Done;\r
2343 }\r
b18e7050 2344\r
70f1d5e7 2345 //\r
93551a01 2346 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
70f1d5e7
ED
2347 //\r
2348 if (mHiiPackageListUpdated) {\r
2349 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2350 mHiiPackageListUpdated = FALSE;\r
2351 break;\r
2352 }\r
5adb8db7
LG
2353 }\r
2354 }\r
2355\r
7936fb6a 2356 //\r
2357 // Load Questions' Value for display\r
2358 //\r
eccfeab1 2359 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2360 if (EFI_ERROR (Status)) {\r
13ad1def 2361 goto Done;\r
7936fb6a 2362 }\r
2363\r
6fd184d0
ED
2364 if (!mFinishRetrieveCall) {\r
2365 //\r
2366 // Finish call RETRIEVE callback for this form.\r
2367 //\r
2368 mFinishRetrieveCall = TRUE;\r
798e4d22 2369\r
6fd184d0
ED
2370 if (ConfigAccess != NULL) {\r
2371 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
2372 if (EFI_ERROR (Status)) {\r
2373 goto Done;\r
2374 }\r
2375\r
2376 //\r
2377 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2378 //\r
2379 if (mHiiPackageListUpdated) {\r
2380 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2381 mHiiPackageListUpdated = FALSE;\r
2382 break;\r
2383 }\r
2384 }\r
eccfeab1
LG
2385 }\r
2386\r
7936fb6a 2387 //\r
2388 // Display form\r
2389 //\r
7c6c064c 2390 Status = DisplayForm ();\r
7936fb6a 2391 if (EFI_ERROR (Status)) {\r
13ad1def 2392 goto Done;\r
7936fb6a 2393 }\r
2394\r
2395 //\r
2396 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2397 //\r
2398 Statement = Selection->Statement;\r
2399 if (Statement != NULL) {\r
13ad1def
LG
2400 if ((ConfigAccess != NULL) && \r
2401 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2402 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2403 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2404 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2405 //\r
2406 // Process dynamic update ref opcode.\r
2407 //\r
2408 if (!EFI_ERROR (Status)) {\r
7c6c064c 2409 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2410 }\r
2411 \r
3dde743f 2412 //\r
8ca6180f 2413 // Callback return error status or status return from process goto opcode.\r
3dde743f 2414 //\r
8ca6180f 2415 if (EFI_ERROR (Status)) {\r
3dde743f 2416 //\r
2417 // Cross reference will not be taken\r
2418 //\r
2419 Selection->FormId = Selection->Form->FormId;\r
2420 Selection->QuestionId = 0;\r
2421 }\r
7936fb6a 2422 }\r
b7891584 2423\r
a6c0ad81
ED
2424 //\r
2425 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2426 //\r
2427 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2428\r
ca2be854
ED
2429 if (!EFI_ERROR (Status) && \r
2430 (Statement->Operand != EFI_IFR_REF_OP) && \r
2431 ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
2432 //\r
2433 // Only question value has been changed, browser will trig CHANGED callback.\r
2434 //\r
798e4d22 2435 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
b7891584 2436 }\r
bfae1330 2437 } else {\r
a6c0ad81 2438 //\r
bfae1330 2439 // Do the question validation.\r
a6c0ad81 2440 //\r
bfae1330
ED
2441 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2442 if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
2443 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
2444 //\r
2445 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2446 //\r
2447 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2448 }\r
7936fb6a 2449 }\r
892eccc8 2450\r
b1239a24
ED
2451 //\r
2452 // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
2453 // trig the gResetFlag.\r
2454 //\r
2455 if ((Status == EFI_SUCCESS) && \r
2456 (Statement->Storage == NULL) && \r
2457 ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2458 gResetRequired = TRUE;\r
2459 }\r
7936fb6a 2460 }\r
7936fb6a 2461\r
7c6c064c
ED
2462 //\r
2463 // Check whether Exit flag is TRUE.\r
2464 //\r
2465 if (gExitRequired) {\r
2466 switch (gBrowserSettingScope) {\r
2467 case SystemLevel:\r
2468 Selection->Action = UI_ACTION_EXIT;\r
2469 break;\r
2470\r
2471 case FormSetLevel:\r
2472 case FormLevel:\r
2473 FindNextMenu (Selection, gBrowserSettingScope);\r
2474 break;\r
2475\r
2476 default:\r
2477 break;\r
2478 }\r
2479\r
2480 gExitRequired = FALSE;\r
2481 }\r
2482\r
5adb8db7
LG
2483 //\r
2484 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2485 // for each question with callback flag.\r
2486 //\r
5adb8db7
LG
2487 if ((ConfigAccess != NULL) && \r
2488 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2489 (Selection->Handle != mCurrentHiiHandle) ||\r
2490 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2491 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2492\r
798e4d22 2493 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2494 if (EFI_ERROR (Status)) {\r
2495 goto Done;\r
f4a2af1f 2496 }\r
2497 }\r
5adb8db7 2498 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2499\r
d66e6c16 2500Done:\r
13ad1def
LG
2501 //\r
2502 // Reset current form information to the initial setting when error happens or form exit.\r
2503 //\r
2504 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2505 mCurrentHiiHandle = NULL;\r
2506 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2507 mCurrentFormId = 0;\r
2508 }\r
2509\r
7936fb6a 2510 //\r
2511 // Unregister notify for Form package update\r
2512 //\r
13ad1def
LG
2513 mHiiDatabase->UnregisterPackageNotify (\r
2514 mHiiDatabase,\r
2515 NotifyHandle\r
2516 );\r
7936fb6a 2517 return Status;\r
2518}\r