]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
When need to find varstore in the storage list, based on the extra HiiHandle to find...
[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
798e4d22 163 ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
7c6c064c
ED
164 \r
165 if (mHiiPackageListUpdated) {\r
166 //\r
167 // Package list is updated, force to reparse IFR binary of target Formset\r
168 //\r
169 mHiiPackageListUpdated = FALSE;\r
170 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
171 }\r
172}\r
173\r
174/**\r
175 Refresh the question which has refresh guid event attribute.\r
176 \r
177 @param Event The event which has this function related. \r
178 @param Context The input context info related to this event or the status code return to the caller.\r
179**/\r
180VOID\r
181EFIAPI\r
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 571\r
184f3a02
ED
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
b9feb4bd 613/**\r
b9feb4bd 614\r
7c6c064c
ED
615 Enum all statement in current form, find all the statement can be display and\r
616 add to the display form.\r
b9feb4bd
ED
617\r
618**/\r
619VOID\r
7c6c064c
ED
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
184f3a02 633 UINT32 ExtraAttribute;\r
7c6c064c
ED
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
184f3a02
ED
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
7c6c064c
ED
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
184f3a02
ED
691 //\r
692 // Set the extra attribute.\r
693 //\r
694 DisplayStatement->Attribute |= ExtraAttribute;\r
695\r
7c6c064c
ED
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
07d7dbae
ED
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
8a639069 1047 @param FormSetGuid The formset guid for the request formset.\r
07d7dbae
ED
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
7c6c064c
ED
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
07d7dbae 1132 @param FormsetGuid The formset guid for this formset.\r
7c6c064c
ED
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
7c6c064c 1140DevicePathToHiiHandle (\r
07d7dbae
ED
1141 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1142 IN EFI_GUID *FormsetGuid\r
7936fb6a 1143 )\r
1144{\r
7c6c064c
ED
1145 EFI_STATUS Status;\r
1146 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
7c6c064c
ED
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
7936fb6a 1167\r
1168 //\r
7c6c064c 1169 // Retrieve all HII Handles from HII database\r
7936fb6a 1170 //\r
07d7dbae
ED
1171 HiiHandles = HiiGetHiiHandles (NULL);\r
1172 if (HiiHandles == NULL) {\r
7c6c064c
ED
1173 return NULL;\r
1174 }\r
b9feb4bd 1175\r
7936fb6a 1176 //\r
7c6c064c 1177 // Search Hii Handle by Driver Handle\r
7936fb6a 1178 //\r
7c6c064c 1179 HiiHandle = NULL;\r
07d7dbae 1180 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
7c6c064c
ED
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
07d7dbae
ED
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
7c6c064c
ED
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
7936fb6a 1213\r
7c6c064c
ED
1214**/\r
1215EFI_HII_HANDLE\r
1216FormSetGuidToHiiHandle (\r
1217 EFI_GUID *ComparingGuid\r
1218 )\r
1219{\r
1220 EFI_HII_HANDLE *HiiHandles;\r
7c6c064c 1221 EFI_HII_HANDLE HiiHandle;\r
07d7dbae 1222 UINTN Index;\r
7c6c064c
ED
1223\r
1224 ASSERT (ComparingGuid != NULL);\r
1225\r
1226 HiiHandle = NULL;\r
7936fb6a 1227 //\r
7c6c064c 1228 // Get all the Hii handles\r
7936fb6a 1229 //\r
7c6c064c
ED
1230 HiiHandles = HiiGetHiiHandles (NULL);\r
1231 ASSERT (HiiHandles != NULL);\r
25361615
ED
1232\r
1233 //\r
7c6c064c 1234 // Search for formset of each class type\r
25361615 1235 //\r
7c6c064c 1236 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
07d7dbae
ED
1237 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
1238 HiiHandle = HiiHandles[Index];\r
1239 break;\r
7c6c064c
ED
1240 }\r
1241\r
07d7dbae
ED
1242 if (HiiHandle != NULL) {\r
1243 break;\r
7c6c064c 1244 }\r
7936fb6a 1245 }\r
1246\r
7c6c064c 1247 FreePool (HiiHandles);\r
7936fb6a 1248\r
7c6c064c 1249 return HiiHandle;\r
7936fb6a 1250}\r
1251\r
1252/**\r
7c6c064c
ED
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
7936fb6a 1259\r
7c6c064c 1260 @param Scope Data save or discard scope, form or formset.\r
7936fb6a 1261\r
7c6c064c
ED
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
7936fb6a 1264**/\r
7c6c064c
ED
1265BOOLEAN\r
1266ProcessChangedData (\r
1267 IN OUT UI_MENU_SELECTION *Selection,\r
1268 IN BROWSER_SETTING_SCOPE Scope\r
7936fb6a 1269 )\r
1270{\r
7c6c064c 1271 BOOLEAN RetValue;\r
7936fb6a 1272\r
7c6c064c
ED
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
7936fb6a 1282\r
7c6c064c
ED
1283 case BROWSER_ACTION_NONE:\r
1284 RetValue = FALSE;\r
1285 break;\r
b9feb4bd 1286\r
7c6c064c
ED
1287 default:\r
1288 //\r
1289 // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
1290 //\r
1291 RetValue = FALSE;\r
1292 break;\r
1293 }\r
1294\r
1295 return RetValue;\r
7936fb6a 1296}\r
1297\r
1298/**\r
7c6c064c
ED
1299 Find parent formset menu(the first menu which has different formset) for current menu.\r
1300 If not find, just return to the first menu.\r
7936fb6a 1301\r
7c6c064c 1302 @param Selection The selection info.\r
7936fb6a 1303\r
1304**/\r
7c6c064c
ED
1305VOID\r
1306FindParentFormSet (\r
1307 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1308 )\r
1309{\r
7c6c064c
ED
1310 FORM_ENTRY_INFO *CurrentMenu;\r
1311 FORM_ENTRY_INFO *ParentMenu;\r
25361615 1312\r
7c6c064c
ED
1313 CurrentMenu = Selection->CurrentMenu;\r
1314 ParentMenu = UiFindParentMenu(CurrentMenu);\r
7936fb6a 1315\r
1316 //\r
7c6c064c 1317 // Find a menu which has different formset guid with current.\r
7936fb6a 1318 //\r
7c6c064c
ED
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
7936fb6a 1333\r
7c6c064c 1334 Selection->Statement = NULL;\r
7936fb6a 1335}\r
1336\r
1337/**\r
7c6c064c 1338 Process the goto op code, update the info in the selection structure.\r
7936fb6a 1339\r
7c6c064c
ED
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
7936fb6a 1345**/\r
7c6c064c
ED
1346EFI_STATUS\r
1347ProcessGotoOpCode (\r
1348 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
1349 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1350 )\r
1351{\r
7c6c064c
ED
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
25361615 1361\r
b9feb4bd 1362 //\r
7c6c064c 1363 // Prepare the device path check, get the device path info first.\r
b9feb4bd 1364 //\r
7c6c064c
ED
1365 if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
1366 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
25361615 1367 }\r
b9feb4bd 1368\r
7c6c064c
ED
1369 //\r
1370 // Check whether the device path string is a valid string.\r
1371 //\r
798e4d22 1372 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
7c6c064c
ED
1373 if (Selection->Form->ModalForm) {\r
1374 return Status;\r
1375 }\r
1376\r
25361615 1377 //\r
7c6c064c 1378 // Goto another Hii Package list\r
25361615 1379 //\r
7c6c064c
ED
1380 if (mPathFromText != NULL) {\r
1381 DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
1382 if (DevicePath != NULL) {\r
07d7dbae 1383 HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
7c6c064c
ED
1384 FreePool (DevicePath);\r
1385 }\r
1386 FreePool (StringPtr);\r
1387 } else {\r
7936fb6a 1388 //\r
7c6c064c 1389 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
7936fb6a 1390 //\r
7c6c064c
ED
1391 gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;\r
1392 FreePool (StringPtr);\r
1393 return Status;\r
1394 }\r
25361615 1395\r
7c6c064c
ED
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
7936fb6a 1404 }\r
7936fb6a 1405 }\r
1406 }\r
7936fb6a 1407\r
7c6c064c
ED
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
7936fb6a 1416 }\r
1417\r
7c6c064c
ED
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
7936fb6a 1426 //\r
7c6c064c 1427 // Goto another Formset, check for uncommitted data\r
7936fb6a 1428 //\r
7c6c064c
ED
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
7936fb6a 1434 }\r
7c6c064c 1435 }\r
7936fb6a 1436\r
7c6c064c
ED
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
7936fb6a 1446\r
7c6c064c
ED
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
7936fb6a 1461\r
7c6c064c
ED
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
7936fb6a 1471 }\r
7936fb6a 1472\r
7c6c064c
ED
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
25361615 1478\r
7c6c064c 1479 return Status;\r
7936fb6a 1480}\r
1481\r
1482\r
1483/**\r
7c6c064c 1484 Process Question Config.\r
7936fb6a 1485\r
7c6c064c
ED
1486 @param Selection The UI menu selection.\r
1487 @param Question The Question to be peocessed.\r
7936fb6a 1488\r
7c6c064c
ED
1489 @retval EFI_SUCCESS Question Config process success.\r
1490 @retval Other Question Config process fail.\r
7936fb6a 1491\r
1492**/\r
1493EFI_STATUS\r
7c6c064c
ED
1494ProcessQuestionConfig (\r
1495 IN UI_MENU_SELECTION *Selection,\r
1496 IN FORM_BROWSER_STATEMENT *Question\r
7936fb6a 1497 )\r
1498{\r
7c6c064c
ED
1499 EFI_STATUS Status;\r
1500 CHAR16 *ConfigResp;\r
1501 CHAR16 *Progress;\r
1502 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
7936fb6a 1503\r
7c6c064c
ED
1504 if (Question->QuestionConfig == 0) {\r
1505 return EFI_SUCCESS;\r
1506 }\r
7936fb6a 1507\r
7c6c064c
ED
1508 //\r
1509 // Get <ConfigResp>\r
1510 //\r
1511 ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
1512 if (ConfigResp == NULL) {\r
1513 return EFI_NOT_FOUND;\r
1514 }\r
7936fb6a 1515\r
7c6c064c
ED
1516 //\r
1517 // Send config to Configuration Driver\r
1518 //\r
1519 ConfigAccess = Selection->FormSet->ConfigAccess;\r
1520 if (ConfigAccess == NULL) {\r
1521 return EFI_UNSUPPORTED;\r
7936fb6a 1522 }\r
7c6c064c
ED
1523 Status = ConfigAccess->RouteConfig (\r
1524 ConfigAccess,\r
1525 ConfigResp,\r
1526 &Progress\r
1527 );\r
7936fb6a 1528\r
7c6c064c 1529 return Status;\r
7936fb6a 1530}\r
1531\r
7936fb6a 1532/**\r
1533\r
7c6c064c 1534 Process the user input data.\r
d66e6c16 1535\r
7c6c064c
ED
1536 @param UserInput The user input data.\r
1537 @param ChangeHighlight Whether need to change the highlight statement. \r
d66e6c16 1538\r
7936fb6a 1539 @retval EFI_SUCESSS This function always return successfully for now.\r
1540\r
1541**/\r
1542EFI_STATUS\r
7c6c064c
ED
1543ProcessUserInput (\r
1544 IN USER_INPUT *UserInput,\r
1545 IN BOOLEAN ChangeHighlight\r
7936fb6a 1546 )\r
1547{\r
7c6c064c
ED
1548 EFI_STATUS Status;\r
1549 FORM_BROWSER_STATEMENT *Statement;\r
25361615 1550\r
7c6c064c 1551 Status = EFI_SUCCESS;\r
7936fb6a 1552\r
1553 //\r
7c6c064c 1554 // When Exit from FormDisplay function, one of the below two cases must be true.\r
7936fb6a 1555 //\r
7c6c064c 1556 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
7936fb6a 1557\r
b9feb4bd 1558 //\r
7c6c064c 1559 // Remove the last highligh question id, this id will update when show next form.\r
b9feb4bd 1560 //\r
7c6c064c 1561 gCurrentSelection->QuestionId = 0;\r
7936fb6a 1562\r
7c6c064c
ED
1563 //\r
1564 // First process the Action field in USER_INPUT.\r
1565 //\r
1566 if (UserInput->Action != 0) {\r
1567 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
1568 if (EFI_ERROR (Status)) {\r
1569 return Status;\r
1570 }\r
7936fb6a 1571\r
7c6c064c
ED
1572 //\r
1573 // Clear the highlight info.\r
1574 //\r
1575 gCurrentSelection->Statement = NULL;\r
7936fb6a 1576\r
7c6c064c
ED
1577 if (UserInput->SelectedStatement != NULL) {\r
1578 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1579 ASSERT (Statement != NULL);\r
1580 //\r
1581 // Save the current highlight menu in the menu history data.\r
1582 // which will be used when later browse back to this form.\r
1583 //\r
1584 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1585 //\r
1586 // For statement like text, actio, it not has question id.\r
1587 // So use FakeQuestionId to save the question.\r
1588 //\r
1589 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1590 mCurFakeQestId = Statement->FakeQuestionId;\r
1591 } else {\r
1592 mCurFakeQestId = 0;\r
1593 }\r
1594 }\r
1595 } else {\r
1596 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1597 ASSERT (Statement != NULL);\r
7936fb6a 1598\r
7c6c064c 1599 gCurrentSelection->Statement = Statement;\r
25361615 1600\r
7c6c064c
ED
1601 if (ChangeHighlight) {\r
1602 //\r
1603 // This question is the current user select one,record it and later\r
1604 // show it as the highlight question.\r
1605 //\r
1606 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1607 //\r
1608 // For statement like text, actio, it not has question id.\r
1609 // So use FakeQuestionId to save the question.\r
1610 //\r
1611 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1612 mCurFakeQestId = Statement->FakeQuestionId;\r
1613 } else {\r
1614 mCurFakeQestId = 0;\r
7936fb6a 1615 }\r
7c6c064c 1616 }\r
7936fb6a 1617\r
7c6c064c
ED
1618 switch (Statement->Operand) {\r
1619 case EFI_IFR_REF_OP:\r
1620 Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
1621 break;\r
1622 \r
1623 case EFI_IFR_ACTION_OP:\r
1624 //\r
1625 // Process the Config string <ConfigResp>\r
1626 //\r
1627 Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
1628 break;\r
1629 \r
1630 case EFI_IFR_RESET_BUTTON_OP:\r
7936fb6a 1631 //\r
7c6c064c 1632 // Reset Question to default value specified by DefaultId\r
7936fb6a 1633 //\r
7c6c064c
ED
1634 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
1635 break;\r
1636\r
1637 default:\r
1638 switch (Statement->Operand) {\r
1639 case EFI_IFR_STRING_OP:\r
1640 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1641 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1642 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1643 FreePool (UserInput->InputValue.Buffer);\r
1644 break;\r
1645\r
1646 case EFI_IFR_PASSWORD_OP:\r
1647 if (UserInput->InputValue.Buffer == NULL) {\r
1648 //\r
1649 // User not input new password, just return.\r
1650 //\r
1651 break;\r
1652 }\r
8b0fc5c1 1653\r
7c6c064c
ED
1654 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1655 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1656 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1657 FreePool (UserInput->InputValue.Buffer);\r
8b0fc5c1 1658 //\r
7c6c064c 1659 // Two password match, send it to Configuration Driver\r
8b0fc5c1 1660 //\r
7c6c064c
ED
1661 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
1662 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
1663 //\r
1664 // Clean the value after saved it.\r
1665 //\r
1666 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
1667 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
1668 } else {\r
1669 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
1670 }\r
1671 break;\r
1672\r
1673 case EFI_IFR_ORDERED_LIST_OP:\r
1674 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
1675 break;\r
1676\r
1677 default:\r
1678 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
1679 break;\r
1680 }\r
7c6c064c 1681 break;\r
7936fb6a 1682 }\r
7936fb6a 1683 }\r
1684\r
7936fb6a 1685 return Status;\r
1686}\r
1687\r
1688/**\r
7936fb6a 1689\r
7c6c064c 1690 Display form and wait for user to select one menu option, then return it.\r
7936fb6a 1691\r
7c6c064c 1692 @retval EFI_SUCESSS This function always return successfully for now.\r
48a9d5f7
LG
1693\r
1694**/\r
7c6c064c
ED
1695EFI_STATUS\r
1696DisplayForm (\r
48a9d5f7
LG
1697 VOID\r
1698 )\r
1699{\r
7c6c064c
ED
1700 EFI_STATUS Status;\r
1701 USER_INPUT UserInput;\r
1702 FORM_ENTRY_INFO *CurrentMenu;\r
1703 BOOLEAN ChangeHighlight;\r
48a9d5f7 1704\r
7c6c064c 1705 ZeroMem (&UserInput, sizeof (USER_INPUT));\r
48a9d5f7
LG
1706\r
1707 //\r
7c6c064c 1708 // Update the menu history data.\r
48a9d5f7 1709 //\r
7c6c064c
ED
1710 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
1711 if (CurrentMenu == NULL) {\r
48a9d5f7 1712 //\r
7c6c064c 1713 // Current menu not found, add it to the menu tree\r
25361615 1714 //\r
7c6c064c
ED
1715 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
1716 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
1717 ASSERT (CurrentMenu != NULL);\r
1718 }\r
1719 gCurrentSelection->CurrentMenu = CurrentMenu;\r
48a9d5f7 1720\r
7c6c064c
ED
1721 //\r
1722 // Find currrent highlight statement.\r
1723 //\r
1724 if (gCurrentSelection->QuestionId == 0) {\r
48a9d5f7 1725 //\r
7c6c064c 1726 // Highlight not specified, fetch it from cached menu\r
48a9d5f7 1727 //\r
7c6c064c 1728 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
48a9d5f7 1729 }\r
25361615 1730\r
7c6c064c
ED
1731 //\r
1732 // Evaluate all the Expressions in this Form\r
1733 //\r
1734 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
1735 if (EFI_ERROR (Status)) {\r
1736 return Status;\r
b9feb4bd 1737 }\r
7936fb6a 1738\r
7c6c064c 1739 UpdateDisplayFormData ();\r
25361615 1740\r
7c6c064c
ED
1741 //\r
1742 // Three possible status maybe return.\r
1743 //\r
1744 // EFI_INVALID_PARAMETER: The input dimension info is not valid.\r
1745 // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid\r
1746 // and an valid value has return.\r
1747 // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.\r
1748 //\r
1749 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
1750 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
1751 FreeDisplayFormData();\r
1752 return Status;\r
1753 }\r
25361615 1754\r
7c6c064c
ED
1755 //\r
1756 // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.\r
1757 // in this case, browser need to change the highlight menu.\r
1758 // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist \r
1759 // opcode and new valid value has return, browser core need to adjust\r
1760 // value for this opcode and shows this form again.\r
1761 //\r
1762 ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);\r
25361615 1763\r
7c6c064c 1764 Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
25361615 1765\r
7c6c064c 1766 FreeDisplayFormData();\r
25361615 1767\r
7c6c064c 1768 return Status;\r
7936fb6a 1769}\r
1770\r
1771/**\r
1772 Functions which are registered to receive notification of\r
1773 database events have this prototype. The actual event is encoded\r
1774 in NotifyType. The following table describes how PackageType,\r
1775 PackageGuid, Handle, and Package are used for each of the\r
1776 notification types.\r
1777\r
1778 @param PackageType Package type of the notification.\r
1779\r
1780 @param PackageGuid If PackageType is\r
1781 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
1782 the pointer to the GUID from the Guid\r
1783 field of EFI_HII_PACKAGE_GUID_HEADER.\r
1784 Otherwise, it must be NULL.\r
1785\r
1786 @param Package Points to the package referred to by the\r
1787 notification Handle The handle of the package\r
1788 list which contains the specified package.\r
1789\r
1790 @param Handle The HII handle.\r
1791\r
1792 @param NotifyType The type of change concerning the\r
1793 database. See\r
1794 EFI_HII_DATABASE_NOTIFY_TYPE.\r
1795\r
1796**/\r
1797EFI_STATUS\r
6d3ea23f 1798EFIAPI\r
7936fb6a 1799FormUpdateNotify (\r
1800 IN UINT8 PackageType,\r
1801 IN CONST EFI_GUID *PackageGuid,\r
1802 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
1803 IN EFI_HII_HANDLE Handle,\r
1804 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
1805 )\r
1806{\r
1807 mHiiPackageListUpdated = TRUE;\r
1808\r
1809 return EFI_SUCCESS;\r
1810}\r
1811\r
b18e7050 1812/**\r
7c6c064c 1813 Update the NV flag info for this form set.\r
b18e7050
ED
1814\r
1815 @param FormSet FormSet data structure.\r
1816\r
b18e7050 1817**/\r
7c6c064c
ED
1818BOOLEAN\r
1819IsNvUpdateRequiredForFormSet (\r
b18e7050
ED
1820 IN FORM_BROWSER_FORMSET *FormSet\r
1821 )\r
1822{\r
1823 LIST_ENTRY *Link;\r
1824 FORM_BROWSER_FORM *Form;\r
7c6c064c
ED
1825 BOOLEAN RetVal;\r
1826\r
1827 //\r
1828 // Not finished question initialization, return FALSE.\r
1829 //\r
1830 if (!FormSet->QuestionInited) {\r
1831 return FALSE;\r
1832 }\r
1833\r
1834 RetVal = FALSE;\r
b18e7050
ED
1835\r
1836 Link = GetFirstNode (&FormSet->FormListHead);\r
1837 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1838 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1839\r
7c6c064c
ED
1840 RetVal = IsNvUpdateRequiredForForm(Form);\r
1841 if (RetVal) {\r
1842 break;\r
b9feb4bd
ED
1843 }\r
1844\r
25361615 1845 Link = GetNextNode (&FormSet->FormListHead, Link);\r
b9feb4bd
ED
1846 }\r
1847\r
7c6c064c
ED
1848 return RetVal;\r
1849}\r
1850\r
1851/**\r
1852 Update the NvUpdateRequired flag for a form.\r
1853\r
1854 @param Form Form data structure.\r
1855\r
1856**/\r
1857BOOLEAN\r
1858IsNvUpdateRequiredForForm (\r
1859 IN FORM_BROWSER_FORM *Form\r
1860 )\r
1861{\r
1862 LIST_ENTRY *Link;\r
1863 FORM_BROWSER_STATEMENT *Statement;\r
1864\r
1865 Link = GetFirstNode (&Form->StatementListHead);\r
1866 while (!IsNull (&Form->StatementListHead, Link)) {\r
1867 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1868\r
1869 if (Statement->ValueChanged) {\r
1870 return TRUE;\r
1871 }\r
1872\r
1873 Link = GetNextNode (&Form->StatementListHead, Link);\r
1874 }\r
1875\r
b18e7050
ED
1876 return FALSE;\r
1877}\r
1878\r
1879/**\r
7c6c064c 1880 Check whether the storage data for current form set is changed.\r
b18e7050 1881\r
7c6c064c 1882 @param FormSet FormSet data structure.\r
b18e7050 1883\r
7c6c064c
ED
1884 @retval TRUE Data is changed.\r
1885 @retval FALSE Data is not changed.\r
b18e7050 1886**/\r
7c6c064c
ED
1887BOOLEAN \r
1888IsStorageDataChangedForFormSet (\r
1889 IN FORM_BROWSER_FORMSET *FormSet\r
b18e7050
ED
1890 )\r
1891{\r
1892 LIST_ENTRY *Link;\r
7c6c064c
ED
1893 FORMSET_STORAGE *Storage;\r
1894 BROWSER_STORAGE *BrowserStorage;\r
1895 CHAR16 *ConfigRespNew;\r
1896 CHAR16 *ConfigRespOld;\r
1897 BOOLEAN RetVal;\r
b9feb4bd 1898\r
7c6c064c
ED
1899 RetVal = FALSE;\r
1900 ConfigRespNew = NULL;\r
1901 ConfigRespOld = NULL;\r
b9feb4bd 1902\r
7c6c064c
ED
1903 //\r
1904 // Request current settings from Configuration Driver\r
1905 //\r
1906 Link = GetFirstNode (&FormSet->StorageListHead);\r
1907 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1908 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1909 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1910\r
1911 BrowserStorage = Storage->BrowserStorage;\r
1912\r
1913 if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1914 continue;\r
1915 }\r
1916\r
1917 if (Storage->ElementCount == 0) {\r
1918 continue;\r
1919 }\r
1920\r
1921 StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE);\r
1922 StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE);\r
1923 ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL);\r
1924\r
1925 if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) {\r
1926 RetVal = TRUE;\r
1927 }\r
1928\r
1929 FreePool (ConfigRespNew);\r
1930 ConfigRespNew = NULL;\r
1931\r
1932 FreePool (ConfigRespOld);\r
1933 ConfigRespOld = NULL;\r
1934\r
1935 if (RetVal) {\r
1936 break;\r
1937 }\r
b18e7050 1938 }\r
7c6c064c
ED
1939\r
1940 return RetVal;\r
b18e7050 1941}\r
7c6c064c 1942\r
b18e7050
ED
1943/**\r
1944 Find menu which will show next time.\r
1945\r
1946 @param Selection On input, Selection tell setup browser the information\r
1947 about the Selection, form and formset to be displayed.\r
1948 On output, Selection return the screen item that is selected\r
1949 by user.\r
7c6c064c
ED
1950 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
1951 else, we need to exit current formset.\r
b18e7050 1952 \r
7c6c064c
ED
1953 @retval TRUE Exit current form.\r
1954 @retval FALSE User press ESC and keep in current form.\r
b18e7050
ED
1955**/\r
1956BOOLEAN\r
1957FindNextMenu (\r
7c6c064c
ED
1958 IN OUT UI_MENU_SELECTION *Selection,\r
1959 IN BROWSER_SETTING_SCOPE SettingLevel\r
b18e7050
ED
1960 )\r
1961{\r
7c6c064c
ED
1962 FORM_ENTRY_INFO *CurrentMenu;\r
1963 FORM_ENTRY_INFO *ParentMenu;\r
1964 BROWSER_SETTING_SCOPE Scope;\r
b18e7050
ED
1965 \r
1966 CurrentMenu = Selection->CurrentMenu;\r
7c6c064c
ED
1967 ParentMenu = NULL;\r
1968 Scope = FormSetLevel;\r
b18e7050 1969\r
7c6c064c 1970 if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {\r
b2e444aa
ED
1971 //\r
1972 // we have a parent, so go to the parent menu\r
1973 //\r
7c6c064c
ED
1974 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1975 if (SettingLevel == FormSetLevel) {\r
48a9d5f7 1976 //\r
7c6c064c 1977 // Find a menu which has different formset guid with current.\r
48a9d5f7 1978 //\r
7c6c064c
ED
1979 while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1980 CurrentMenu = ParentMenu;\r
1981 if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {\r
1982 break;\r
1983 }\r
b9feb4bd 1984 }\r
25361615 1985\r
7c6c064c
ED
1986 if (ParentMenu != NULL) {\r
1987 Scope = FormSetLevel;\r
1988 }\r
48a9d5f7 1989 } else {\r
7c6c064c 1990 Scope = FormLevel;\r
48a9d5f7 1991 }\r
7c6c064c
ED
1992 } else {\r
1993 Scope = FormSetLevel;\r
b18e7050 1994 }\r
25361615
ED
1995 }\r
1996\r
b9feb4bd 1997 //\r
7c6c064c 1998 // Form Level Check whether the data is changed.\r
b9feb4bd 1999 //\r
7c6c064c
ED
2000 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
2001 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
2002 if (!ProcessChangedData(Selection, Scope)) {\r
25361615
ED
2003 return FALSE;\r
2004 }\r
7c6c064c 2005 }\r
b9feb4bd 2006\r
7c6c064c
ED
2007 if (ParentMenu != NULL) {\r
2008 //\r
2009 // ParentMenu is found. Then, go to it.\r
2010 //\r
2011 if (Scope == FormLevel) {\r
2012 Selection->Action = UI_ACTION_REFRESH_FORM;\r
25361615 2013 } else {\r
7c6c064c
ED
2014 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2015 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
2016 Selection->Handle = ParentMenu->HiiHandle;\r
25361615 2017 }\r
25361615 2018\r
7c6c064c
ED
2019 Selection->Statement = NULL;\r
2020\r
2021 Selection->FormId = ParentMenu->FormId;\r
2022 Selection->QuestionId = ParentMenu->QuestionId;\r
2023\r
2024 //\r
2025 // Clear highlight record for this menu\r
2026 //\r
25361615 2027 CurrentMenu->QuestionId = 0;\r
7c6c064c 2028 return FALSE;\r
25361615
ED
2029 }\r
2030\r
7c6c064c
ED
2031 //\r
2032 // Current in root page, exit the SendForm\r
2033 //\r
25361615 2034 Selection->Action = UI_ACTION_EXIT;\r
7c6c064c 2035\r
b18e7050
ED
2036 return TRUE;\r
2037}\r
2038\r
2039/**\r
2040 Call the call back function for the question and process the return action.\r
2041\r
2042 @param Selection On input, Selection tell setup browser the information\r
2043 about the Selection, form and formset to be displayed.\r
2044 On output, Selection return the screen item that is selected\r
2045 by user.\r
798e4d22
ED
2046 @param FormSet The formset this question belong to.\r
2047 @param Form The form this question belong to.\r
b18e7050
ED
2048 @param Question The Question which need to call.\r
2049 @param Action The action request.\r
2050 @param SkipSaveOrDiscard Whether skip save or discard action.\r
2051\r
2052 @retval EFI_SUCCESS The call back function excutes successfully.\r
2053 @return Other value if the call back function failed to excute. \r
2054**/\r
2055EFI_STATUS \r
2056ProcessCallBackFunction (\r
2057 IN OUT UI_MENU_SELECTION *Selection,\r
798e4d22
ED
2058 IN FORM_BROWSER_FORMSET *FormSet,\r
2059 IN FORM_BROWSER_FORM *Form,\r
b18e7050
ED
2060 IN FORM_BROWSER_STATEMENT *Question,\r
2061 IN EFI_BROWSER_ACTION Action,\r
2062 IN BOOLEAN SkipSaveOrDiscard\r
2063 )\r
2064{\r
2065 EFI_STATUS Status;\r
2066 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2067 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2068 EFI_HII_VALUE *HiiValue;\r
2069 EFI_IFR_TYPE_VALUE *TypeValue;\r
2070 FORM_BROWSER_STATEMENT *Statement;\r
2071 BOOLEAN SubmitFormIsRequired;\r
b18e7050
ED
2072 BOOLEAN DiscardFormIsRequired;\r
2073 BOOLEAN NeedExit;\r
2074 LIST_ENTRY *Link;\r
48a9d5f7 2075 BROWSER_SETTING_SCOPE SettingLevel;\r
e6cc2ab3
ED
2076 EFI_IFR_TYPE_VALUE BackUpValue;\r
2077 UINT8 *BackUpBuffer;\r
b18e7050 2078\r
798e4d22 2079 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 2080 SubmitFormIsRequired = FALSE;\r
48a9d5f7 2081 SettingLevel = FormSetLevel;\r
b18e7050
ED
2082 DiscardFormIsRequired = FALSE;\r
2083 NeedExit = FALSE;\r
2084 Status = EFI_SUCCESS;\r
2085 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 2086 BackUpBuffer = NULL;\r
b18e7050
ED
2087\r
2088 if (ConfigAccess == NULL) {\r
2089 return EFI_SUCCESS;\r
2090 }\r
2091\r
798e4d22
ED
2092 Link = GetFirstNode (&Form->StatementListHead);\r
2093 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 2094 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 2095 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
2096\r
2097 //\r
2098 // if Question != NULL, only process the question. Else, process all question in this form.\r
2099 //\r
2100 if ((Question != NULL) && (Statement != Question)) {\r
2101 continue;\r
2102 }\r
2103 \r
2104 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2105 continue;\r
2106 }\r
2107\r
2108 //\r
2109 // Check whether Statement is disabled.\r
2110 //\r
31585af4 2111 if (Statement->Expression != NULL) {\r
798e4d22 2112 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
2113 continue;\r
2114 }\r
2115 }\r
2116\r
2117 HiiValue = &Statement->HiiValue;\r
2118 TypeValue = &HiiValue->Value;\r
2119 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2120 //\r
2121 // For OrderedList, passing in the value buffer to Callback()\r
2122 //\r
2123 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2124 }\r
e6cc2ab3
ED
2125\r
2126 //\r
2127 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
2128 //\r
2129 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2130 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2131 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
2132 } else {\r
2133 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
2134 }\r
2135 }\r
2136\r
b18e7050
ED
2137 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2138 Status = ConfigAccess->Callback (\r
2139 ConfigAccess,\r
2140 Action,\r
2141 Statement->QuestionId,\r
2142 HiiValue->Type,\r
2143 TypeValue,\r
2144 &ActionRequest\r
2145 );\r
2146 if (!EFI_ERROR (Status)) {\r
3a4e7a3e
ED
2147 //\r
2148 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
2149 //\r
2150 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2151 switch (ActionRequest) {\r
2152 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 2153 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 2154 gResetRequired = TRUE;\r
7c6c064c 2155 NeedExit = TRUE;\r
3a4e7a3e 2156 break;\r
b18e7050 2157\r
3a4e7a3e
ED
2158 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2159 SubmitFormIsRequired = TRUE;\r
7c6c064c 2160 NeedExit = TRUE;\r
3a4e7a3e 2161 break;\r
b18e7050 2162\r
3a4e7a3e 2163 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 2164 DiscardFormIsRequired = TRUE;\r
7c6c064c 2165 NeedExit = TRUE;\r
3a4e7a3e 2166 break;\r
b18e7050 2167\r
3a4e7a3e
ED
2168 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
2169 SubmitFormIsRequired = TRUE;\r
2170 SettingLevel = FormLevel;\r
2171 NeedExit = TRUE;\r
2172 break;\r
b18e7050 2173\r
3a4e7a3e
ED
2174 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
2175 DiscardFormIsRequired = TRUE;\r
7c6c064c 2176 SettingLevel = FormLevel;\r
3a4e7a3e
ED
2177 NeedExit = TRUE;\r
2178 break;\r
b18e7050 2179\r
3a4e7a3e
ED
2180 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
2181 SubmitFormIsRequired = TRUE;\r
2182 SettingLevel = FormLevel;\r
2183 break;\r
b18e7050 2184\r
3a4e7a3e
ED
2185 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
2186 DiscardFormIsRequired = TRUE;\r
2187 SettingLevel = FormLevel;\r
2188 break;\r
b18e7050 2189\r
3a4e7a3e
ED
2190 default:\r
2191 break;\r
2192 }\r
b18e7050 2193 }\r
8ca6180f
ED
2194\r
2195 //\r
2196 // According the spec, return value from call back of "changing" and \r
2197 // "retrieve" should update to the question's temp buffer.\r
2198 //\r
2199 if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2200 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
8ca6180f 2201 }\r
c4042207 2202 } else {\r
e6cc2ab3
ED
2203 //\r
2204 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2205 // then the browser will use the value passed to Callback() and ignore the \r
2206 // value returned by Callback(). \r
2207 //\r
2208 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2209 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2210 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2211 } else {\r
2212 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2213 }\r
2214\r
798e4d22 2215 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
e6cc2ab3
ED
2216 }\r
2217\r
b18e7050 2218 //\r
c4042207
ED
2219 // According the spec, return fail from call back of "changing" and \r
2220 // "retrieve", should restore the question's value.\r
b18e7050 2221 //\r
e6cc2ab3
ED
2222 if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || \r
2223 Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2224 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2225 }\r
2226\r
2227 if (Status == EFI_UNSUPPORTED) {\r
2228 //\r
2229 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2230 //\r
2231 Status = EFI_SUCCESS;\r
2232 }\r
b18e7050 2233 }\r
e6cc2ab3
ED
2234\r
2235 if (BackUpBuffer != NULL) {\r
2236 FreePool (BackUpBuffer);\r
2237 }\r
b18e7050
ED
2238 }\r
2239\r
2240 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2241 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2242 }\r
2243\r
2244 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2245 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2246 }\r
2247\r
2248 if (NeedExit) {\r
7c6c064c 2249 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2250 }\r
2251\r
2252 return Status;\r
2253}\r
2254\r
9776099f
ED
2255/**\r
2256 Call the retrieve type call back function for one question to get the initialize data.\r
2257 \r
2258 This function only used when in the initialize stage, because in this stage, the \r
2259 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2260\r
2261 @param ConfigAccess The config access protocol produced by the hii driver.\r
2262 @param Statement The Question which need to call.\r
2263\r
2264 @retval EFI_SUCCESS The call back function excutes successfully.\r
2265 @return Other value if the call back function failed to excute. \r
2266**/\r
2267EFI_STATUS \r
2268ProcessRetrieveForQuestion (\r
2269 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
2270 IN FORM_BROWSER_STATEMENT *Statement\r
2271 )\r
2272{\r
2273 EFI_STATUS Status;\r
2274 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2275 EFI_HII_VALUE *HiiValue;\r
2276 EFI_IFR_TYPE_VALUE *TypeValue;\r
2277\r
2278 Status = EFI_SUCCESS;\r
2279 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2280 \r
2281 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2282 return EFI_UNSUPPORTED;\r
2283 }\r
2284\r
2285 HiiValue = &Statement->HiiValue;\r
2286 TypeValue = &HiiValue->Value;\r
2287 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2288 //\r
2289 // For OrderedList, passing in the value buffer to Callback()\r
2290 //\r
2291 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2292 }\r
2293 \r
2294 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2295 Status = ConfigAccess->Callback (\r
2296 ConfigAccess,\r
2297 EFI_BROWSER_ACTION_RETRIEVE,\r
2298 Statement->QuestionId,\r
2299 HiiValue->Type,\r
2300 TypeValue,\r
2301 &ActionRequest\r
2302 );\r
2303 return Status;\r
2304}\r
2305\r
7936fb6a 2306/**\r
2307 The worker function that send the displays to the screen. On output,\r
2308 the selection made by user is returned.\r
2309\r
2310 @param Selection On input, Selection tell setup browser the information\r
2311 about the Selection, form and formset to be displayed.\r
2312 On output, Selection return the screen item that is selected\r
2313 by user.\r
2314\r
2315 @retval EFI_SUCCESS The page is displayed successfully.\r
2316 @return Other value if the page failed to be diplayed.\r
2317\r
2318**/\r
2319EFI_STATUS\r
2320SetupBrowser (\r
2321 IN OUT UI_MENU_SELECTION *Selection\r
2322 )\r
2323{\r
2324 EFI_STATUS Status;\r
2325 LIST_ENTRY *Link;\r
7936fb6a 2326 EFI_HANDLE NotifyHandle;\r
7936fb6a 2327 FORM_BROWSER_STATEMENT *Statement;\r
2328 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2329\r
5adb8db7 2330 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2331\r
2332 //\r
2333 // Register notify for Form package update\r
2334 //\r
2335 Status = mHiiDatabase->RegisterPackageNotify (\r
2336 mHiiDatabase,\r
8d00a0f1 2337 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2338 NULL,\r
2339 FormUpdateNotify,\r
2340 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2341 &NotifyHandle\r
2342 );\r
2343 if (EFI_ERROR (Status)) {\r
2344 return Status;\r
2345 }\r
2346\r
798e4d22
ED
2347 if ((Selection->Handle != mCurrentHiiHandle) ||\r
2348 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid))) {\r
2349 gFinishRetrieveCall = FALSE;\r
2350 }\r
2351\r
d66e6c16 2352 //\r
2353 // Initialize current settings of Questions in this FormSet\r
2354 //\r
7c6c064c 2355 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2356\r
2357 //\r
7c6c064c 2358 // Initilize Action field.\r
b9feb4bd 2359 //\r
7c6c064c
ED
2360 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2361\r
2362 //\r
2363 // Clean the mCurFakeQestId value is formset refreshed.\r
2364 //\r
2365 mCurFakeQestId = 0;\r
48a9d5f7 2366\r
7936fb6a 2367 do {\r
54f8fc6d
ED
2368 //\r
2369 // IFR is updated, force to reparse the IFR binary\r
2370 //\r
2371 if (mHiiPackageListUpdated) {\r
2372 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2373 mHiiPackageListUpdated = FALSE;\r
2374 break;\r
2375 }\r
2376\r
7936fb6a 2377 //\r
2378 // Initialize Selection->Form\r
2379 //\r
2380 if (Selection->FormId == 0) {\r
2381 //\r
2382 // Zero FormId indicates display the first Form in a FormSet\r
2383 //\r
2384 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2385\r
2386 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2387 Selection->FormId = Selection->Form->FormId;\r
2388 } else {\r
2389 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2390 }\r
2391\r
0a1147ed
LG
2392 if (Selection->Form == NULL) {\r
2393 //\r
2394 // No Form to display\r
2395 //\r
13ad1def
LG
2396 Status = EFI_NOT_FOUND;\r
2397 goto Done;\r
0a1147ed
LG
2398 }\r
2399\r
0c66bc76
LG
2400 //\r
2401 // Check Form is suppressed.\r
2402 //\r
2403 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2404 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2405 //\r
2406 // Form is suppressed. \r
2407 //\r
7c6c064c 2408 gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
13ad1def
LG
2409 Status = EFI_NOT_FOUND;\r
2410 goto Done;\r
0c66bc76
LG
2411 }\r
2412 }\r
5adb8db7 2413\r
5adb8db7
LG
2414 //\r
2415 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2416 // for each question with callback flag.\r
2417 // New form may be the first form, or the different form after another form close.\r
2418 //\r
13ad1def
LG
2419 if ((ConfigAccess != NULL) &&\r
2420 ((Selection->Handle != mCurrentHiiHandle) ||\r
2421 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2422 (Selection->FormId != mCurrentFormId))) {\r
13ad1def
LG
2423 //\r
2424 // Keep current form information\r
2425 //\r
2426 mCurrentHiiHandle = Selection->Handle;\r
2427 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2428 mCurrentFormId = Selection->FormId;\r
2429\r
798e4d22 2430 Status = ProcessCallBackFunction (Selection, gCurrentSelection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
b18e7050
ED
2431 if (EFI_ERROR (Status)) {\r
2432 goto Done;\r
5adb8db7 2433 }\r
b18e7050 2434\r
5adb8db7
LG
2435 //\r
2436 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2437 //\r
2438 if (mHiiPackageListUpdated) {\r
2439 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2440 mHiiPackageListUpdated = FALSE;\r
6a05469c 2441 break;\r
5adb8db7
LG
2442 }\r
2443 }\r
2444\r
7936fb6a 2445 //\r
2446 // Load Questions' Value for display\r
2447 //\r
eccfeab1 2448 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2449 if (EFI_ERROR (Status)) {\r
13ad1def 2450 goto Done;\r
7936fb6a 2451 }\r
2452\r
798e4d22
ED
2453 //\r
2454 // Finish call RETRIEVE callback for this formset.\r
2455 //\r
2456 gFinishRetrieveCall = TRUE;\r
2457\r
eccfeab1
LG
2458 //\r
2459 // IFR is updated during callback of read value, force to reparse the IFR binary\r
2460 //\r
2461 if (mHiiPackageListUpdated) {\r
2462 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2463 mHiiPackageListUpdated = FALSE;\r
6a05469c 2464 break;\r
eccfeab1
LG
2465 }\r
2466\r
7936fb6a 2467 //\r
2468 // Display form\r
2469 //\r
7c6c064c 2470 Status = DisplayForm ();\r
7936fb6a 2471 if (EFI_ERROR (Status)) {\r
13ad1def 2472 goto Done;\r
7936fb6a 2473 }\r
2474\r
2475 //\r
2476 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2477 //\r
2478 Statement = Selection->Statement;\r
2479 if (Statement != NULL) {\r
13ad1def
LG
2480 if ((ConfigAccess != NULL) && \r
2481 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2482 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2483 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2484 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2485 //\r
2486 // Process dynamic update ref opcode.\r
2487 //\r
2488 if (!EFI_ERROR (Status)) {\r
7c6c064c 2489 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2490 }\r
2491 \r
3dde743f 2492 //\r
8ca6180f 2493 // Callback return error status or status return from process goto opcode.\r
3dde743f 2494 //\r
8ca6180f 2495 if (EFI_ERROR (Status)) {\r
3dde743f 2496 //\r
2497 // Cross reference will not be taken\r
2498 //\r
2499 Selection->FormId = Selection->Form->FormId;\r
2500 Selection->QuestionId = 0;\r
2501 }\r
7936fb6a 2502 }\r
b7891584 2503\r
3a4e7a3e 2504 if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
798e4d22 2505 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
b7891584 2506 }\r
e6cc2ab3
ED
2507 } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
2508 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
7936fb6a 2509 }\r
7936fb6a 2510 }\r
7936fb6a 2511\r
7c6c064c
ED
2512 //\r
2513 // Check whether Exit flag is TRUE.\r
2514 //\r
2515 if (gExitRequired) {\r
2516 switch (gBrowserSettingScope) {\r
2517 case SystemLevel:\r
2518 Selection->Action = UI_ACTION_EXIT;\r
2519 break;\r
2520\r
2521 case FormSetLevel:\r
2522 case FormLevel:\r
2523 FindNextMenu (Selection, gBrowserSettingScope);\r
2524 break;\r
2525\r
2526 default:\r
2527 break;\r
2528 }\r
2529\r
2530 gExitRequired = FALSE;\r
2531 }\r
2532\r
5adb8db7
LG
2533 //\r
2534 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2535 // for each question with callback flag.\r
2536 //\r
5adb8db7
LG
2537 if ((ConfigAccess != NULL) && \r
2538 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2539 (Selection->Handle != mCurrentHiiHandle) ||\r
2540 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2541 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2542\r
798e4d22 2543 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2544 if (EFI_ERROR (Status)) {\r
2545 goto Done;\r
f4a2af1f 2546 }\r
2547 }\r
5adb8db7 2548 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2549\r
d66e6c16 2550Done:\r
13ad1def
LG
2551 //\r
2552 // Reset current form information to the initial setting when error happens or form exit.\r
2553 //\r
2554 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2555 mCurrentHiiHandle = NULL;\r
2556 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2557 mCurrentFormId = 0;\r
2558 }\r
2559\r
7936fb6a 2560 //\r
2561 // Unregister notify for Form package update\r
2562 //\r
13ad1def
LG
2563 mHiiDatabase->UnregisterPackageNotify (\r
2564 mHiiDatabase,\r
2565 NotifyHandle\r
2566 );\r
7936fb6a 2567 return Status;\r
2568}\r