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