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