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