]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Refine the load form sets process for BrowserCallback function.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for UI presentation.\r
3\r
892eccc8 4Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
7936fb6a 16\r
17BOOLEAN mHiiPackageListUpdated;\r
18UI_MENU_SELECTION *gCurrentSelection;\r
13ad1def
LG
19EFI_HII_HANDLE mCurrentHiiHandle = NULL;\r
20EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
21UINT16 mCurrentFormId = 0;\r
7c6c064c
ED
22EFI_EVENT mValueChangedEvent = NULL;\r
23LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);\r
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
892eccc8
ED
966/**\r
967 Update the ValueChanged status for questions in this form.\r
968\r
969 @param FormSet FormSet data structure.\r
970 @param Form Form data structure.\r
971\r
972**/\r
973VOID \r
974UpdateStatementStatusForForm (\r
975 IN FORM_BROWSER_FORMSET *FormSet,\r
976 IN FORM_BROWSER_FORM *Form\r
977 )\r
978{\r
979 LIST_ENTRY *Link;\r
980 FORM_BROWSER_STATEMENT *Question;\r
981\r
982 Link = GetFirstNode (&Form->StatementListHead);\r
983 while (!IsNull (&Form->StatementListHead, Link)) {\r
984 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
985 Link = GetNextNode (&Form->StatementListHead, Link);\r
986\r
987 IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
988 }\r
989}\r
990\r
991/**\r
992 Update the ValueChanged status for questions in this formset.\r
993\r
994 @param FormSet FormSet data structure.\r
995\r
996**/\r
997VOID \r
998UpdateStatementStatusForFormSet (\r
999 IN FORM_BROWSER_FORMSET *FormSet\r
1000 )\r
1001{\r
1002 LIST_ENTRY *Link;\r
1003 FORM_BROWSER_FORM *Form;\r
1004\r
1005 Link = GetFirstNode (&FormSet->FormListHead);\r
1006 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1007 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1008 Link = GetNextNode (&FormSet->FormListHead, Link);\r
1009\r
1010 UpdateStatementStatusForForm (FormSet, Form);\r
1011 }\r
1012}\r
1013\r
1014/**\r
1015 Update the ValueChanged status for questions.\r
1016\r
1017 @param FormSet FormSet data structure.\r
1018 @param Form Form data structure.\r
1019 @param SettingScope Setting Scope for Default action.\r
1020\r
1021**/\r
1022VOID \r
1023UpdateStatementStatus (\r
1024 IN FORM_BROWSER_FORMSET *FormSet,\r
1025 IN FORM_BROWSER_FORM *Form, \r
1026 IN BROWSER_SETTING_SCOPE SettingScope\r
1027 )\r
1028{\r
1029 LIST_ENTRY *Link;\r
1030 FORM_BROWSER_FORMSET *LocalFormSet;\r
1031\r
1032 switch (SettingScope) {\r
1033 case SystemLevel:\r
1034 Link = GetFirstNode (&gBrowserFormSetList);\r
1035 while (!IsNull (&gBrowserFormSetList, Link)) {\r
1036 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
1037 Link = GetNextNode (&gBrowserFormSetList, Link);\r
1038 if (!ValidateFormSet(LocalFormSet)) {\r
1039 continue;\r
1040 }\r
1041\r
1042 UpdateStatementStatusForFormSet (LocalFormSet);\r
1043 }\r
1044 break;\r
1045\r
1046 case FormSetLevel:\r
1047 UpdateStatementStatusForFormSet (FormSet);\r
1048 break;\r
1049\r
1050 case FormLevel:\r
1051 UpdateStatementStatusForForm (FormSet, Form);\r
1052 break;\r
1053\r
1054 default:\r
1055 break;\r
1056 }\r
1057}\r
1058\r
7c6c064c
ED
1059/**\r
1060\r
1061 Process the action request in user input.\r
1062\r
1063 @param Action The user input action request info.\r
1064 @param DefaultId The user input default Id info.\r
1065\r
1066 @retval EFI_SUCESSS This function always return successfully for now.\r
1067\r
1068**/\r
1069EFI_STATUS \r
1070ProcessAction (\r
1071 IN UINT32 Action,\r
1072 IN UINT16 DefaultId\r
1073 )\r
1074{\r
1075 EFI_STATUS Status;\r
1076\r
1077 //\r
1078 // This is caused by use press ESC, and it should not combine with other action type.\r
1079 //\r
1080 if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {\r
1081 FindNextMenu (gCurrentSelection, FormLevel);\r
1082 return EFI_SUCCESS;\r
1083 }\r
1084\r
1085 //\r
1086 // Below is normal hotkey trigged action, these action maybe combine with each other.\r
1087 //\r
1088 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
1089 DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
1090 }\r
1091\r
1092 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
1093 ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
892eccc8 1094 UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
7c6c064c
ED
1095 }\r
1096\r
1097 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
1098 Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
1099 if (EFI_ERROR (Status)) {\r
1100 gBrowserStatus = BROWSER_SUBMIT_FAIL;\r
1101 }\r
1102 }\r
1103\r
1104 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
1105 gResetRequired = TRUE;\r
1106 }\r
1107\r
1108 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
1109 //\r
1110 // Form Exit without saving, Similar to ESC Key.\r
1111 // FormSet Exit without saving, Exit SendForm.\r
1112 // System Exit without saving, CallExitHandler and Exit SendForm.\r
1113 //\r
1114 DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
1115 if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {\r
1116 FindNextMenu (gCurrentSelection, gBrowserSettingScope);\r
1117 } else if (gBrowserSettingScope == SystemLevel) {\r
1118 if (ExitHandlerFunction != NULL) {\r
1119 ExitHandlerFunction ();\r
1120 }\r
1121 gCurrentSelection->Action = UI_ACTION_EXIT;\r
1122 }\r
1123 }\r
1124\r
1125 return EFI_SUCCESS;\r
1126}\r
1127\r
07d7dbae
ED
1128/**\r
1129 Check whether the formset guid is in this Hii package list.\r
1130\r
1131 @param HiiHandle The HiiHandle for this HII package list.\r
8a639069 1132 @param FormSetGuid The formset guid for the request formset.\r
07d7dbae
ED
1133\r
1134 @retval TRUE Find the formset guid.\r
1135 @retval FALSE Not found the formset guid.\r
1136\r
1137**/\r
1138BOOLEAN\r
1139GetFormsetGuidFromHiiHandle (\r
1140 IN EFI_HII_HANDLE HiiHandle,\r
1141 IN EFI_GUID *FormSetGuid\r
1142 )\r
1143{\r
1144 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1145 UINTN BufferSize;\r
1146 UINT32 Offset;\r
1147 UINT32 Offset2;\r
1148 UINT32 PackageListLength;\r
1149 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1150 UINT8 *Package;\r
1151 UINT8 *OpCodeData;\r
1152 EFI_STATUS Status;\r
1153 BOOLEAN FindGuid;\r
1154\r
1155 BufferSize = 0;\r
1156 HiiPackageList = NULL;\r
1157 FindGuid = FALSE;\r
1158 \r
1159 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1160 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1161 HiiPackageList = AllocatePool (BufferSize);\r
1162 ASSERT (HiiPackageList != NULL);\r
1163\r
1164 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
1165 }\r
1166 if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
1167 return FALSE;\r
1168 }\r
1169\r
1170 //\r
1171 // Get Form package from this HII package List\r
1172 //\r
1173 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1174 Offset2 = 0;\r
1175 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
1176\r
1177 while (Offset < PackageListLength) {\r
1178 Package = ((UINT8 *) HiiPackageList) + Offset;\r
1179 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
1180 Offset += PackageHeader.Length;\r
1181\r
1182 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1183 //\r
1184 // Search FormSet in this Form Package\r
1185 //\r
1186 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
1187 while (Offset2 < PackageHeader.Length) {\r
1188 OpCodeData = Package + Offset2;\r
1189\r
1190 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
1191 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){\r
1192 FindGuid = TRUE;\r
1193 break;\r
1194 }\r
1195 }\r
1196\r
1197 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
1198 }\r
1199 }\r
1200 if (FindGuid) {\r
1201 break;\r
1202 }\r
1203 }\r
1204\r
1205 FreePool (HiiPackageList);\r
1206\r
1207 return FindGuid;\r
1208}\r
7c6c064c
ED
1209\r
1210/**\r
1211 Find HII Handle in the HII database associated with given Device Path.\r
1212\r
1213 If DevicePath is NULL, then ASSERT.\r
1214\r
1215 @param DevicePath Device Path associated with the HII package list\r
1216 handle.\r
07d7dbae 1217 @param FormsetGuid The formset guid for this formset.\r
7c6c064c
ED
1218\r
1219 @retval Handle HII package list Handle associated with the Device\r
1220 Path.\r
1221 @retval NULL Hii Package list handle is not found.\r
1222\r
1223**/\r
1224EFI_HII_HANDLE\r
7c6c064c 1225DevicePathToHiiHandle (\r
07d7dbae
ED
1226 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1227 IN EFI_GUID *FormsetGuid\r
7936fb6a 1228 )\r
1229{\r
7c6c064c
ED
1230 EFI_STATUS Status;\r
1231 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
7c6c064c
ED
1232 UINTN Index;\r
1233 EFI_HANDLE Handle;\r
1234 EFI_HANDLE DriverHandle;\r
1235 EFI_HII_HANDLE *HiiHandles;\r
1236 EFI_HII_HANDLE HiiHandle;\r
1237\r
1238 ASSERT (DevicePath != NULL);\r
1239\r
1240 TmpDevicePath = DevicePath;\r
1241 //\r
1242 // Locate Device Path Protocol handle buffer\r
1243 //\r
1244 Status = gBS->LocateDevicePath (\r
1245 &gEfiDevicePathProtocolGuid,\r
1246 &TmpDevicePath,\r
1247 &DriverHandle\r
1248 );\r
1249 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
1250 return NULL;\r
1251 }\r
7936fb6a 1252\r
1253 //\r
7c6c064c 1254 // Retrieve all HII Handles from HII database\r
7936fb6a 1255 //\r
07d7dbae
ED
1256 HiiHandles = HiiGetHiiHandles (NULL);\r
1257 if (HiiHandles == NULL) {\r
7c6c064c
ED
1258 return NULL;\r
1259 }\r
b9feb4bd 1260\r
7936fb6a 1261 //\r
7c6c064c 1262 // Search Hii Handle by Driver Handle\r
7936fb6a 1263 //\r
7c6c064c 1264 HiiHandle = NULL;\r
07d7dbae 1265 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
7c6c064c
ED
1266 Status = mHiiDatabase->GetPackageListHandle (\r
1267 mHiiDatabase,\r
1268 HiiHandles[Index],\r
1269 &Handle\r
1270 );\r
1271 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
07d7dbae
ED
1272 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {\r
1273 HiiHandle = HiiHandles[Index];\r
1274 break;\r
1275 }\r
1276\r
1277 if (HiiHandle != NULL) {\r
1278 break;\r
1279 }\r
7c6c064c
ED
1280 }\r
1281 }\r
1282\r
1283 FreePool (HiiHandles);\r
1284 return HiiHandle;\r
1285}\r
1286\r
1287/**\r
1288 Find HII Handle in the HII database associated with given form set guid.\r
1289\r
1290 If FormSetGuid is NULL, then ASSERT.\r
1291\r
1292 @param ComparingGuid FormSet Guid associated with the HII package list\r
1293 handle.\r
1294\r
1295 @retval Handle HII package list Handle associated with the Device\r
1296 Path.\r
1297 @retval NULL Hii Package list handle is not found.\r
7936fb6a 1298\r
7c6c064c
ED
1299**/\r
1300EFI_HII_HANDLE\r
1301FormSetGuidToHiiHandle (\r
1302 EFI_GUID *ComparingGuid\r
1303 )\r
1304{\r
1305 EFI_HII_HANDLE *HiiHandles;\r
7c6c064c 1306 EFI_HII_HANDLE HiiHandle;\r
07d7dbae 1307 UINTN Index;\r
7c6c064c
ED
1308\r
1309 ASSERT (ComparingGuid != NULL);\r
1310\r
1311 HiiHandle = NULL;\r
7936fb6a 1312 //\r
7c6c064c 1313 // Get all the Hii handles\r
7936fb6a 1314 //\r
7c6c064c
ED
1315 HiiHandles = HiiGetHiiHandles (NULL);\r
1316 ASSERT (HiiHandles != NULL);\r
25361615
ED
1317\r
1318 //\r
7c6c064c 1319 // Search for formset of each class type\r
25361615 1320 //\r
7c6c064c 1321 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
07d7dbae
ED
1322 if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
1323 HiiHandle = HiiHandles[Index];\r
1324 break;\r
7c6c064c
ED
1325 }\r
1326\r
07d7dbae
ED
1327 if (HiiHandle != NULL) {\r
1328 break;\r
7c6c064c 1329 }\r
7936fb6a 1330 }\r
1331\r
7c6c064c 1332 FreePool (HiiHandles);\r
7936fb6a 1333\r
7c6c064c 1334 return HiiHandle;\r
7936fb6a 1335}\r
1336\r
1337/**\r
7c6c064c
ED
1338 check how to process the changed data in current form or form set.\r
1339\r
1340 @param Selection On input, Selection tell setup browser the information\r
1341 about the Selection, form and formset to be displayed.\r
1342 On output, Selection return the screen item that is selected\r
1343 by user.\r
7936fb6a 1344\r
7c6c064c 1345 @param Scope Data save or discard scope, form or formset.\r
7936fb6a 1346\r
7c6c064c
ED
1347 @retval TRUE Success process the changed data, will return to the parent form.\r
1348 @retval FALSE Reject to process the changed data, will stay at current form.\r
7936fb6a 1349**/\r
7c6c064c
ED
1350BOOLEAN\r
1351ProcessChangedData (\r
1352 IN OUT UI_MENU_SELECTION *Selection,\r
1353 IN BROWSER_SETTING_SCOPE Scope\r
7936fb6a 1354 )\r
1355{\r
7c6c064c 1356 BOOLEAN RetValue;\r
7936fb6a 1357\r
7c6c064c
ED
1358 RetValue = TRUE;\r
1359 switch (mFormDisplay->ConfirmDataChange()) {\r
6307a8b6 1360 case BROWSER_ACTION_DISCARD:\r
7c6c064c
ED
1361 DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
1362 break;\r
1363 \r
6307a8b6 1364 case BROWSER_ACTION_SUBMIT:\r
7c6c064c
ED
1365 SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
1366 break;\r
7936fb6a 1367\r
6307a8b6 1368 case BROWSER_ACTION_NONE:\r
7c6c064c
ED
1369 RetValue = FALSE;\r
1370 break;\r
b9feb4bd 1371\r
7c6c064c
ED
1372 default:\r
1373 //\r
1374 // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
1375 //\r
1376 RetValue = FALSE;\r
1377 break;\r
1378 }\r
1379\r
1380 return RetValue;\r
7936fb6a 1381}\r
1382\r
1383/**\r
7c6c064c
ED
1384 Find parent formset menu(the first menu which has different formset) for current menu.\r
1385 If not find, just return to the first menu.\r
7936fb6a 1386\r
7c6c064c 1387 @param Selection The selection info.\r
7936fb6a 1388\r
1389**/\r
7c6c064c
ED
1390VOID\r
1391FindParentFormSet (\r
1392 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1393 )\r
1394{\r
7c6c064c
ED
1395 FORM_ENTRY_INFO *CurrentMenu;\r
1396 FORM_ENTRY_INFO *ParentMenu;\r
25361615 1397\r
7c6c064c
ED
1398 CurrentMenu = Selection->CurrentMenu;\r
1399 ParentMenu = UiFindParentMenu(CurrentMenu);\r
7936fb6a 1400\r
1401 //\r
7c6c064c 1402 // Find a menu which has different formset guid with current.\r
7936fb6a 1403 //\r
7c6c064c
ED
1404 while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1405 CurrentMenu = ParentMenu;\r
1406 ParentMenu = UiFindParentMenu(CurrentMenu);\r
1407 }\r
1408\r
1409 if (ParentMenu != NULL) {\r
1410 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
1411 Selection->Handle = ParentMenu->HiiHandle;\r
1412 Selection->FormId = ParentMenu->FormId;\r
1413 Selection->QuestionId = ParentMenu->QuestionId;\r
1414 } else {\r
1415 Selection->FormId = CurrentMenu->FormId;\r
1416 Selection->QuestionId = CurrentMenu->QuestionId;\r
1417 }\r
7936fb6a 1418\r
7c6c064c 1419 Selection->Statement = NULL;\r
7936fb6a 1420}\r
1421\r
1422/**\r
7c6c064c 1423 Process the goto op code, update the info in the selection structure.\r
7936fb6a 1424\r
7c6c064c
ED
1425 @param Statement The statement belong to goto op code.\r
1426 @param Selection The selection info.\r
1427\r
1428 @retval EFI_SUCCESS The menu process successfully.\r
1429 @return Other value if the process failed.\r
7936fb6a 1430**/\r
7c6c064c
ED
1431EFI_STATUS\r
1432ProcessGotoOpCode (\r
1433 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
1434 IN OUT UI_MENU_SELECTION *Selection\r
7936fb6a 1435 )\r
1436{\r
7c6c064c
ED
1437 CHAR16 *StringPtr;\r
1438 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1439 FORM_BROWSER_FORM *RefForm;\r
1440 EFI_STATUS Status;\r
1441 EFI_HII_HANDLE HiiHandle;\r
1442 \r
1443 Status = EFI_SUCCESS;\r
1444 StringPtr = NULL;\r
1445 HiiHandle = NULL;\r
25361615 1446\r
b9feb4bd 1447 //\r
7c6c064c 1448 // Prepare the device path check, get the device path info first.\r
b9feb4bd 1449 //\r
7c6c064c
ED
1450 if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
1451 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
25361615 1452 }\r
b9feb4bd 1453\r
7c6c064c
ED
1454 //\r
1455 // Check whether the device path string is a valid string.\r
1456 //\r
798e4d22 1457 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
7c6c064c
ED
1458 if (Selection->Form->ModalForm) {\r
1459 return Status;\r
1460 }\r
1461\r
25361615 1462 //\r
7c6c064c 1463 // Goto another Hii Package list\r
25361615 1464 //\r
7c6c064c
ED
1465 if (mPathFromText != NULL) {\r
1466 DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
1467 if (DevicePath != NULL) {\r
07d7dbae 1468 HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
7c6c064c
ED
1469 FreePool (DevicePath);\r
1470 }\r
1471 FreePool (StringPtr);\r
1472 } else {\r
7936fb6a 1473 //\r
7c6c064c 1474 // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
7936fb6a 1475 //\r
7c6c064c
ED
1476 gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;\r
1477 FreePool (StringPtr);\r
1478 return Status;\r
1479 }\r
25361615 1480\r
7c6c064c
ED
1481 if (HiiHandle != Selection->Handle) {\r
1482 //\r
1483 // Goto another Formset, check for uncommitted data\r
1484 //\r
1485 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
1486 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
1487 if (!ProcessChangedData(Selection, FormSetLevel)) {\r
1488 return EFI_SUCCESS;\r
7936fb6a 1489 }\r
7936fb6a 1490 }\r
1491 }\r
7936fb6a 1492\r
7c6c064c
ED
1493 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1494 Selection->Handle = HiiHandle;\r
1495 if (Selection->Handle == NULL) {\r
1496 //\r
1497 // If target Hii Handle not found, exit current formset.\r
1498 //\r
1499 FindParentFormSet(Selection);\r
1500 return EFI_SUCCESS;\r
7936fb6a 1501 }\r
1502\r
7c6c064c
ED
1503 CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
1504 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1505 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1506 } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
1507 if (Selection->Form->ModalForm) {\r
1508 return Status;\r
1509 }\r
1510 if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {\r
7936fb6a 1511 //\r
7c6c064c 1512 // Goto another Formset, check for uncommitted data\r
7936fb6a 1513 //\r
7c6c064c
ED
1514 if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
1515 IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
1516 if (!ProcessChangedData(Selection, FormSetLevel)) {\r
1517 return EFI_SUCCESS;\r
1518 }\r
7936fb6a 1519 }\r
7c6c064c 1520 }\r
7936fb6a 1521\r
7c6c064c
ED
1522 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1523 Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
1524 if (Selection->Handle == NULL) {\r
1525 //\r
1526 // If target Hii Handle not found, exit current formset.\r
1527 //\r
1528 FindParentFormSet(Selection);\r
1529 return EFI_SUCCESS;\r
1530 }\r
7936fb6a 1531\r
7c6c064c
ED
1532 CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
1533 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1534 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1535 } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
1536 //\r
1537 // Goto another Form, check for uncommitted data\r
1538 //\r
1539 if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {\r
1540 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {\r
1541 if (!ProcessChangedData (Selection, FormLevel)) {\r
1542 return EFI_SUCCESS;\r
1543 }\r
1544 }\r
1545 }\r
7936fb6a 1546\r
7c6c064c
ED
1547 RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
1548 if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
1549 if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
1550 //\r
1551 // Form is suppressed. \r
1552 //\r
1553 gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
1554 return EFI_SUCCESS;\r
1555 }\r
7936fb6a 1556 }\r
7936fb6a 1557\r
7c6c064c
ED
1558 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
1559 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1560 } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
1561 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
1562 }\r
25361615 1563\r
7c6c064c 1564 return Status;\r
7936fb6a 1565}\r
1566\r
1567\r
1568/**\r
7c6c064c 1569 Process Question Config.\r
7936fb6a 1570\r
7c6c064c
ED
1571 @param Selection The UI menu selection.\r
1572 @param Question The Question to be peocessed.\r
7936fb6a 1573\r
7c6c064c
ED
1574 @retval EFI_SUCCESS Question Config process success.\r
1575 @retval Other Question Config process fail.\r
7936fb6a 1576\r
1577**/\r
1578EFI_STATUS\r
7c6c064c
ED
1579ProcessQuestionConfig (\r
1580 IN UI_MENU_SELECTION *Selection,\r
1581 IN FORM_BROWSER_STATEMENT *Question\r
7936fb6a 1582 )\r
1583{\r
7c6c064c
ED
1584 EFI_STATUS Status;\r
1585 CHAR16 *ConfigResp;\r
1586 CHAR16 *Progress;\r
7936fb6a 1587\r
7c6c064c
ED
1588 if (Question->QuestionConfig == 0) {\r
1589 return EFI_SUCCESS;\r
1590 }\r
7936fb6a 1591\r
7c6c064c
ED
1592 //\r
1593 // Get <ConfigResp>\r
1594 //\r
1595 ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
1596 if (ConfigResp == NULL) {\r
1597 return EFI_NOT_FOUND;\r
1598 }\r
7936fb6a 1599\r
7c6c064c
ED
1600 //\r
1601 // Send config to Configuration Driver\r
1602 //\r
7248790e
ED
1603 Status = mHiiConfigRouting->RouteConfig (\r
1604 mHiiConfigRouting,\r
7c6c064c
ED
1605 ConfigResp,\r
1606 &Progress\r
1607 );\r
7936fb6a 1608\r
7c6c064c 1609 return Status;\r
7936fb6a 1610}\r
1611\r
7936fb6a 1612/**\r
1613\r
7c6c064c 1614 Process the user input data.\r
d66e6c16 1615\r
7c6c064c
ED
1616 @param UserInput The user input data.\r
1617 @param ChangeHighlight Whether need to change the highlight statement. \r
d66e6c16 1618\r
7936fb6a 1619 @retval EFI_SUCESSS This function always return successfully for now.\r
1620\r
1621**/\r
1622EFI_STATUS\r
7c6c064c
ED
1623ProcessUserInput (\r
1624 IN USER_INPUT *UserInput,\r
1625 IN BOOLEAN ChangeHighlight\r
7936fb6a 1626 )\r
1627{\r
7c6c064c
ED
1628 EFI_STATUS Status;\r
1629 FORM_BROWSER_STATEMENT *Statement;\r
25361615 1630\r
7c6c064c 1631 Status = EFI_SUCCESS;\r
7936fb6a 1632\r
1633 //\r
7c6c064c 1634 // When Exit from FormDisplay function, one of the below two cases must be true.\r
7936fb6a 1635 //\r
7c6c064c 1636 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
7936fb6a 1637\r
b9feb4bd 1638 //\r
7c6c064c 1639 // Remove the last highligh question id, this id will update when show next form.\r
b9feb4bd 1640 //\r
7c6c064c 1641 gCurrentSelection->QuestionId = 0;\r
7936fb6a 1642\r
7c6c064c
ED
1643 //\r
1644 // First process the Action field in USER_INPUT.\r
1645 //\r
1646 if (UserInput->Action != 0) {\r
1647 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
1648 if (EFI_ERROR (Status)) {\r
1649 return Status;\r
1650 }\r
7936fb6a 1651\r
7c6c064c
ED
1652 //\r
1653 // Clear the highlight info.\r
1654 //\r
1655 gCurrentSelection->Statement = NULL;\r
7936fb6a 1656\r
7c6c064c
ED
1657 if (UserInput->SelectedStatement != NULL) {\r
1658 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1659 ASSERT (Statement != NULL);\r
1660 //\r
1661 // Save the current highlight menu in the menu history data.\r
1662 // which will be used when later browse back to this form.\r
1663 //\r
1664 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1665 //\r
1666 // For statement like text, actio, it not has question id.\r
1667 // So use FakeQuestionId to save the question.\r
1668 //\r
1669 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1670 mCurFakeQestId = Statement->FakeQuestionId;\r
1671 } else {\r
1672 mCurFakeQestId = 0;\r
1673 }\r
1674 }\r
1675 } else {\r
1676 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1677 ASSERT (Statement != NULL);\r
7936fb6a 1678\r
7c6c064c 1679 gCurrentSelection->Statement = Statement;\r
25361615 1680\r
7c6c064c
ED
1681 if (ChangeHighlight) {\r
1682 //\r
1683 // This question is the current user select one,record it and later\r
1684 // show it as the highlight question.\r
1685 //\r
1686 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1687 //\r
1688 // For statement like text, actio, it not has question id.\r
1689 // So use FakeQuestionId to save the question.\r
1690 //\r
1691 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1692 mCurFakeQestId = Statement->FakeQuestionId;\r
1693 } else {\r
1694 mCurFakeQestId = 0;\r
7936fb6a 1695 }\r
7c6c064c 1696 }\r
7936fb6a 1697\r
7c6c064c
ED
1698 switch (Statement->Operand) {\r
1699 case EFI_IFR_REF_OP:\r
1700 Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
1701 break;\r
1702 \r
1703 case EFI_IFR_ACTION_OP:\r
1704 //\r
1705 // Process the Config string <ConfigResp>\r
1706 //\r
1707 Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
1708 break;\r
1709 \r
1710 case EFI_IFR_RESET_BUTTON_OP:\r
7936fb6a 1711 //\r
7c6c064c 1712 // Reset Question to default value specified by DefaultId\r
7936fb6a 1713 //\r
7c6c064c 1714 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
892eccc8 1715 UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
7c6c064c
ED
1716 break;\r
1717\r
1718 default:\r
1719 switch (Statement->Operand) {\r
1720 case EFI_IFR_STRING_OP:\r
1721 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1722 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1723 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1724 FreePool (UserInput->InputValue.Buffer);\r
1725 break;\r
1726\r
1727 case EFI_IFR_PASSWORD_OP:\r
1728 if (UserInput->InputValue.Buffer == NULL) {\r
1729 //\r
1730 // User not input new password, just return.\r
1731 //\r
1732 break;\r
1733 }\r
8b0fc5c1 1734\r
7c6c064c
ED
1735 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1736 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1737 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1738 FreePool (UserInput->InputValue.Buffer);\r
8b0fc5c1 1739 //\r
7c6c064c 1740 // Two password match, send it to Configuration Driver\r
8b0fc5c1 1741 //\r
7c6c064c
ED
1742 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
1743 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
1744 //\r
1745 // Clean the value after saved it.\r
1746 //\r
1747 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
1748 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
1749 } else {\r
1750 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
1751 }\r
1752 break;\r
1753\r
1754 case EFI_IFR_ORDERED_LIST_OP:\r
1755 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
1756 break;\r
1757\r
1758 default:\r
1759 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
1760 break;\r
1761 }\r
7c6c064c 1762 break;\r
7936fb6a 1763 }\r
7936fb6a 1764 }\r
1765\r
7936fb6a 1766 return Status;\r
1767}\r
1768\r
1769/**\r
7936fb6a 1770\r
7c6c064c 1771 Display form and wait for user to select one menu option, then return it.\r
7936fb6a 1772\r
7c6c064c 1773 @retval EFI_SUCESSS This function always return successfully for now.\r
48a9d5f7
LG
1774\r
1775**/\r
7c6c064c
ED
1776EFI_STATUS\r
1777DisplayForm (\r
48a9d5f7
LG
1778 VOID\r
1779 )\r
1780{\r
7c6c064c
ED
1781 EFI_STATUS Status;\r
1782 USER_INPUT UserInput;\r
1783 FORM_ENTRY_INFO *CurrentMenu;\r
1784 BOOLEAN ChangeHighlight;\r
48a9d5f7 1785\r
7c6c064c 1786 ZeroMem (&UserInput, sizeof (USER_INPUT));\r
48a9d5f7
LG
1787\r
1788 //\r
7c6c064c 1789 // Update the menu history data.\r
48a9d5f7 1790 //\r
7c6c064c
ED
1791 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
1792 if (CurrentMenu == NULL) {\r
48a9d5f7 1793 //\r
7c6c064c 1794 // Current menu not found, add it to the menu tree\r
25361615 1795 //\r
7c6c064c
ED
1796 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
1797 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
1798 ASSERT (CurrentMenu != NULL);\r
1799 }\r
1800 gCurrentSelection->CurrentMenu = CurrentMenu;\r
48a9d5f7 1801\r
7c6c064c
ED
1802 //\r
1803 // Find currrent highlight statement.\r
1804 //\r
1805 if (gCurrentSelection->QuestionId == 0) {\r
48a9d5f7 1806 //\r
7c6c064c 1807 // Highlight not specified, fetch it from cached menu\r
48a9d5f7 1808 //\r
7c6c064c 1809 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
48a9d5f7 1810 }\r
25361615 1811\r
7c6c064c
ED
1812 //\r
1813 // Evaluate all the Expressions in this Form\r
1814 //\r
1815 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
1816 if (EFI_ERROR (Status)) {\r
1817 return Status;\r
b9feb4bd 1818 }\r
7936fb6a 1819\r
7c6c064c 1820 UpdateDisplayFormData ();\r
25361615 1821\r
7c6c064c
ED
1822 //\r
1823 // Three possible status maybe return.\r
1824 //\r
1825 // EFI_INVALID_PARAMETER: The input dimension info is not valid.\r
1826 // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid\r
1827 // and an valid value has return.\r
1828 // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.\r
1829 //\r
1830 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
1831 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
1832 FreeDisplayFormData();\r
1833 return Status;\r
1834 }\r
25361615 1835\r
7c6c064c
ED
1836 //\r
1837 // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.\r
1838 // in this case, browser need to change the highlight menu.\r
1839 // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist \r
1840 // opcode and new valid value has return, browser core need to adjust\r
1841 // value for this opcode and shows this form again.\r
1842 //\r
1843 ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);\r
25361615 1844\r
7c6c064c 1845 Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
25361615 1846\r
7c6c064c 1847 FreeDisplayFormData();\r
25361615 1848\r
7c6c064c 1849 return Status;\r
7936fb6a 1850}\r
1851\r
1852/**\r
1853 Functions which are registered to receive notification of\r
1854 database events have this prototype. The actual event is encoded\r
1855 in NotifyType. The following table describes how PackageType,\r
1856 PackageGuid, Handle, and Package are used for each of the\r
1857 notification types.\r
1858\r
1859 @param PackageType Package type of the notification.\r
1860\r
1861 @param PackageGuid If PackageType is\r
1862 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
1863 the pointer to the GUID from the Guid\r
1864 field of EFI_HII_PACKAGE_GUID_HEADER.\r
1865 Otherwise, it must be NULL.\r
1866\r
1867 @param Package Points to the package referred to by the\r
1868 notification Handle The handle of the package\r
1869 list which contains the specified package.\r
1870\r
1871 @param Handle The HII handle.\r
1872\r
1873 @param NotifyType The type of change concerning the\r
1874 database. See\r
1875 EFI_HII_DATABASE_NOTIFY_TYPE.\r
1876\r
1877**/\r
1878EFI_STATUS\r
6d3ea23f 1879EFIAPI\r
7936fb6a 1880FormUpdateNotify (\r
1881 IN UINT8 PackageType,\r
1882 IN CONST EFI_GUID *PackageGuid,\r
1883 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
1884 IN EFI_HII_HANDLE Handle,\r
1885 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
1886 )\r
1887{\r
1888 mHiiPackageListUpdated = TRUE;\r
1889\r
1890 return EFI_SUCCESS;\r
1891}\r
1892\r
b18e7050 1893/**\r
7c6c064c 1894 Update the NV flag info for this form set.\r
b18e7050
ED
1895\r
1896 @param FormSet FormSet data structure.\r
1897\r
b18e7050 1898**/\r
7c6c064c
ED
1899BOOLEAN\r
1900IsNvUpdateRequiredForFormSet (\r
b18e7050
ED
1901 IN FORM_BROWSER_FORMSET *FormSet\r
1902 )\r
1903{\r
1904 LIST_ENTRY *Link;\r
1905 FORM_BROWSER_FORM *Form;\r
7c6c064c
ED
1906 BOOLEAN RetVal;\r
1907\r
1908 //\r
1909 // Not finished question initialization, return FALSE.\r
1910 //\r
1911 if (!FormSet->QuestionInited) {\r
1912 return FALSE;\r
1913 }\r
1914\r
1915 RetVal = FALSE;\r
b18e7050
ED
1916\r
1917 Link = GetFirstNode (&FormSet->FormListHead);\r
1918 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1919 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1920\r
7c6c064c
ED
1921 RetVal = IsNvUpdateRequiredForForm(Form);\r
1922 if (RetVal) {\r
1923 break;\r
b9feb4bd
ED
1924 }\r
1925\r
25361615 1926 Link = GetNextNode (&FormSet->FormListHead, Link);\r
b9feb4bd
ED
1927 }\r
1928\r
7c6c064c
ED
1929 return RetVal;\r
1930}\r
1931\r
1932/**\r
1933 Update the NvUpdateRequired flag for a form.\r
1934\r
1935 @param Form Form data structure.\r
1936\r
1937**/\r
1938BOOLEAN\r
1939IsNvUpdateRequiredForForm (\r
1940 IN FORM_BROWSER_FORM *Form\r
1941 )\r
1942{\r
1943 LIST_ENTRY *Link;\r
1944 FORM_BROWSER_STATEMENT *Statement;\r
1945\r
1946 Link = GetFirstNode (&Form->StatementListHead);\r
1947 while (!IsNull (&Form->StatementListHead, Link)) {\r
1948 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1949\r
1950 if (Statement->ValueChanged) {\r
1951 return TRUE;\r
1952 }\r
1953\r
1954 Link = GetNextNode (&Form->StatementListHead, Link);\r
1955 }\r
1956\r
b18e7050
ED
1957 return FALSE;\r
1958}\r
1959\r
b18e7050
ED
1960/**\r
1961 Find menu which will show next time.\r
1962\r
1963 @param Selection On input, Selection tell setup browser the information\r
1964 about the Selection, form and formset to be displayed.\r
1965 On output, Selection return the screen item that is selected\r
1966 by user.\r
7c6c064c
ED
1967 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
1968 else, we need to exit current formset.\r
b18e7050 1969 \r
7c6c064c
ED
1970 @retval TRUE Exit current form.\r
1971 @retval FALSE User press ESC and keep in current form.\r
b18e7050
ED
1972**/\r
1973BOOLEAN\r
1974FindNextMenu (\r
7c6c064c
ED
1975 IN OUT UI_MENU_SELECTION *Selection,\r
1976 IN BROWSER_SETTING_SCOPE SettingLevel\r
b18e7050
ED
1977 )\r
1978{\r
7c6c064c
ED
1979 FORM_ENTRY_INFO *CurrentMenu;\r
1980 FORM_ENTRY_INFO *ParentMenu;\r
1981 BROWSER_SETTING_SCOPE Scope;\r
b18e7050
ED
1982 \r
1983 CurrentMenu = Selection->CurrentMenu;\r
7c6c064c
ED
1984 ParentMenu = NULL;\r
1985 Scope = FormSetLevel;\r
b18e7050 1986\r
7c6c064c 1987 if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {\r
b2e444aa
ED
1988 //\r
1989 // we have a parent, so go to the parent menu\r
1990 //\r
7c6c064c
ED
1991 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1992 if (SettingLevel == FormSetLevel) {\r
48a9d5f7 1993 //\r
7c6c064c 1994 // Find a menu which has different formset guid with current.\r
48a9d5f7 1995 //\r
7c6c064c
ED
1996 while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1997 CurrentMenu = ParentMenu;\r
1998 if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {\r
1999 break;\r
2000 }\r
b9feb4bd 2001 }\r
25361615 2002\r
7c6c064c
ED
2003 if (ParentMenu != NULL) {\r
2004 Scope = FormSetLevel;\r
2005 }\r
48a9d5f7 2006 } else {\r
7c6c064c 2007 Scope = FormLevel;\r
48a9d5f7 2008 }\r
7c6c064c
ED
2009 } else {\r
2010 Scope = FormSetLevel;\r
b18e7050 2011 }\r
25361615
ED
2012 }\r
2013\r
b9feb4bd 2014 //\r
7c6c064c 2015 // Form Level Check whether the data is changed.\r
b9feb4bd 2016 //\r
7c6c064c
ED
2017 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
2018 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
2019 if (!ProcessChangedData(Selection, Scope)) {\r
25361615
ED
2020 return FALSE;\r
2021 }\r
7c6c064c 2022 }\r
b9feb4bd 2023\r
7c6c064c
ED
2024 if (ParentMenu != NULL) {\r
2025 //\r
2026 // ParentMenu is found. Then, go to it.\r
2027 //\r
2028 if (Scope == FormLevel) {\r
2029 Selection->Action = UI_ACTION_REFRESH_FORM;\r
25361615 2030 } else {\r
7c6c064c
ED
2031 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2032 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
2033 Selection->Handle = ParentMenu->HiiHandle;\r
25361615 2034 }\r
25361615 2035\r
7c6c064c
ED
2036 Selection->Statement = NULL;\r
2037\r
2038 Selection->FormId = ParentMenu->FormId;\r
2039 Selection->QuestionId = ParentMenu->QuestionId;\r
2040\r
2041 //\r
2042 // Clear highlight record for this menu\r
2043 //\r
25361615 2044 CurrentMenu->QuestionId = 0;\r
7c6c064c 2045 return FALSE;\r
25361615
ED
2046 }\r
2047\r
7c6c064c
ED
2048 //\r
2049 // Current in root page, exit the SendForm\r
2050 //\r
25361615 2051 Selection->Action = UI_ACTION_EXIT;\r
7c6c064c 2052\r
b18e7050
ED
2053 return TRUE;\r
2054}\r
2055\r
2056/**\r
2057 Call the call back function for the question and process the return action.\r
2058\r
2059 @param Selection On input, Selection tell setup browser the information\r
2060 about the Selection, form and formset to be displayed.\r
2061 On output, Selection return the screen item that is selected\r
2062 by user.\r
798e4d22
ED
2063 @param FormSet The formset this question belong to.\r
2064 @param Form The form this question belong to.\r
b18e7050
ED
2065 @param Question The Question which need to call.\r
2066 @param Action The action request.\r
2067 @param SkipSaveOrDiscard Whether skip save or discard action.\r
2068\r
2069 @retval EFI_SUCCESS The call back function excutes successfully.\r
2070 @return Other value if the call back function failed to excute. \r
2071**/\r
2072EFI_STATUS \r
2073ProcessCallBackFunction (\r
2074 IN OUT UI_MENU_SELECTION *Selection,\r
798e4d22
ED
2075 IN FORM_BROWSER_FORMSET *FormSet,\r
2076 IN FORM_BROWSER_FORM *Form,\r
b18e7050
ED
2077 IN FORM_BROWSER_STATEMENT *Question,\r
2078 IN EFI_BROWSER_ACTION Action,\r
2079 IN BOOLEAN SkipSaveOrDiscard\r
2080 )\r
2081{\r
2082 EFI_STATUS Status;\r
2083 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2084 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2085 EFI_HII_VALUE *HiiValue;\r
2086 EFI_IFR_TYPE_VALUE *TypeValue;\r
2087 FORM_BROWSER_STATEMENT *Statement;\r
2088 BOOLEAN SubmitFormIsRequired;\r
b18e7050
ED
2089 BOOLEAN DiscardFormIsRequired;\r
2090 BOOLEAN NeedExit;\r
2091 LIST_ENTRY *Link;\r
48a9d5f7 2092 BROWSER_SETTING_SCOPE SettingLevel;\r
e6cc2ab3
ED
2093 EFI_IFR_TYPE_VALUE BackUpValue;\r
2094 UINT8 *BackUpBuffer;\r
b18e7050 2095\r
798e4d22 2096 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 2097 SubmitFormIsRequired = FALSE;\r
48a9d5f7 2098 SettingLevel = FormSetLevel;\r
b18e7050
ED
2099 DiscardFormIsRequired = FALSE;\r
2100 NeedExit = FALSE;\r
2101 Status = EFI_SUCCESS;\r
2102 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 2103 BackUpBuffer = NULL;\r
b18e7050
ED
2104\r
2105 if (ConfigAccess == NULL) {\r
2106 return EFI_SUCCESS;\r
2107 }\r
2108\r
798e4d22
ED
2109 Link = GetFirstNode (&Form->StatementListHead);\r
2110 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 2111 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 2112 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
2113\r
2114 //\r
2115 // if Question != NULL, only process the question. Else, process all question in this form.\r
2116 //\r
2117 if ((Question != NULL) && (Statement != Question)) {\r
2118 continue;\r
2119 }\r
2120 \r
2121 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2122 continue;\r
2123 }\r
2124\r
2125 //\r
2126 // Check whether Statement is disabled.\r
2127 //\r
31585af4 2128 if (Statement->Expression != NULL) {\r
798e4d22 2129 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
2130 continue;\r
2131 }\r
2132 }\r
2133\r
2134 HiiValue = &Statement->HiiValue;\r
2135 TypeValue = &HiiValue->Value;\r
2136 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2137 //\r
2138 // For OrderedList, passing in the value buffer to Callback()\r
2139 //\r
2140 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2141 }\r
e6cc2ab3
ED
2142\r
2143 //\r
2144 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
2145 //\r
2146 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2147 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2148 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
2149 } else {\r
2150 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
2151 }\r
2152 }\r
2153\r
b18e7050
ED
2154 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2155 Status = ConfigAccess->Callback (\r
2156 ConfigAccess,\r
2157 Action,\r
2158 Statement->QuestionId,\r
2159 HiiValue->Type,\r
2160 TypeValue,\r
2161 &ActionRequest\r
2162 );\r
2163 if (!EFI_ERROR (Status)) {\r
3a4e7a3e
ED
2164 //\r
2165 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
2166 //\r
2167 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2168 switch (ActionRequest) {\r
2169 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 2170 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 2171 gResetRequired = TRUE;\r
7c6c064c 2172 NeedExit = TRUE;\r
3a4e7a3e 2173 break;\r
b18e7050 2174\r
3a4e7a3e
ED
2175 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2176 SubmitFormIsRequired = TRUE;\r
7c6c064c 2177 NeedExit = TRUE;\r
3a4e7a3e 2178 break;\r
b18e7050 2179\r
3a4e7a3e 2180 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 2181 DiscardFormIsRequired = TRUE;\r
7c6c064c 2182 NeedExit = TRUE;\r
3a4e7a3e 2183 break;\r
b18e7050 2184\r
3a4e7a3e
ED
2185 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
2186 SubmitFormIsRequired = TRUE;\r
2187 SettingLevel = FormLevel;\r
2188 NeedExit = TRUE;\r
2189 break;\r
b18e7050 2190\r
3a4e7a3e
ED
2191 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
2192 DiscardFormIsRequired = TRUE;\r
7c6c064c 2193 SettingLevel = FormLevel;\r
3a4e7a3e
ED
2194 NeedExit = TRUE;\r
2195 break;\r
b18e7050 2196\r
3a4e7a3e
ED
2197 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
2198 SubmitFormIsRequired = TRUE;\r
2199 SettingLevel = FormLevel;\r
2200 break;\r
b18e7050 2201\r
3a4e7a3e
ED
2202 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
2203 DiscardFormIsRequired = TRUE;\r
2204 SettingLevel = FormLevel;\r
2205 break;\r
b18e7050 2206\r
3a4e7a3e
ED
2207 default:\r
2208 break;\r
2209 }\r
b18e7050 2210 }\r
8ca6180f
ED
2211\r
2212 //\r
2213 // According the spec, return value from call back of "changing" and \r
2214 // "retrieve" should update to the question's temp buffer.\r
2215 //\r
2216 if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2217 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
8ca6180f 2218 }\r
c4042207 2219 } else {\r
e6cc2ab3
ED
2220 //\r
2221 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2222 // then the browser will use the value passed to Callback() and ignore the \r
2223 // value returned by Callback(). \r
2224 //\r
2225 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2226 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2227 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2228 } else {\r
2229 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2230 }\r
2231\r
798e4d22 2232 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
e6cc2ab3
ED
2233 }\r
2234\r
b18e7050 2235 //\r
c4042207
ED
2236 // According the spec, return fail from call back of "changing" and \r
2237 // "retrieve", should restore the question's value.\r
b18e7050 2238 //\r
e6cc2ab3
ED
2239 if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || \r
2240 Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2241 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2242 }\r
2243\r
2244 if (Status == EFI_UNSUPPORTED) {\r
2245 //\r
2246 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2247 //\r
2248 Status = EFI_SUCCESS;\r
2249 }\r
b18e7050 2250 }\r
e6cc2ab3
ED
2251\r
2252 if (BackUpBuffer != NULL) {\r
2253 FreePool (BackUpBuffer);\r
2254 }\r
b18e7050
ED
2255 }\r
2256\r
2257 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2258 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2259 }\r
2260\r
2261 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2262 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2263 }\r
2264\r
2265 if (NeedExit) {\r
7c6c064c 2266 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2267 }\r
2268\r
2269 return Status;\r
2270}\r
2271\r
9776099f
ED
2272/**\r
2273 Call the retrieve type call back function for one question to get the initialize data.\r
2274 \r
2275 This function only used when in the initialize stage, because in this stage, the \r
2276 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2277\r
2278 @param ConfigAccess The config access protocol produced by the hii driver.\r
2279 @param Statement The Question which need to call.\r
2280\r
2281 @retval EFI_SUCCESS The call back function excutes successfully.\r
2282 @return Other value if the call back function failed to excute. \r
2283**/\r
2284EFI_STATUS \r
2285ProcessRetrieveForQuestion (\r
2286 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
2287 IN FORM_BROWSER_STATEMENT *Statement\r
2288 )\r
2289{\r
2290 EFI_STATUS Status;\r
2291 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2292 EFI_HII_VALUE *HiiValue;\r
2293 EFI_IFR_TYPE_VALUE *TypeValue;\r
2294\r
2295 Status = EFI_SUCCESS;\r
2296 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
70f1d5e7
ED
2297\r
2298 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
9776099f
ED
2299 return EFI_UNSUPPORTED;\r
2300 }\r
2301\r
2302 HiiValue = &Statement->HiiValue;\r
2303 TypeValue = &HiiValue->Value;\r
2304 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2305 //\r
2306 // For OrderedList, passing in the value buffer to Callback()\r
2307 //\r
2308 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2309 }\r
2310 \r
2311 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2312 Status = ConfigAccess->Callback (\r
2313 ConfigAccess,\r
2314 EFI_BROWSER_ACTION_RETRIEVE,\r
2315 Statement->QuestionId,\r
2316 HiiValue->Type,\r
2317 TypeValue,\r
2318 &ActionRequest\r
2319 );\r
2320 return Status;\r
2321}\r
2322\r
7936fb6a 2323/**\r
2324 The worker function that send the displays to the screen. On output,\r
2325 the selection made by user is returned.\r
2326\r
2327 @param Selection On input, Selection tell setup browser the information\r
2328 about the Selection, form and formset to be displayed.\r
2329 On output, Selection return the screen item that is selected\r
2330 by user.\r
2331\r
2332 @retval EFI_SUCCESS The page is displayed successfully.\r
2333 @return Other value if the page failed to be diplayed.\r
2334\r
2335**/\r
2336EFI_STATUS\r
2337SetupBrowser (\r
2338 IN OUT UI_MENU_SELECTION *Selection\r
2339 )\r
2340{\r
2341 EFI_STATUS Status;\r
2342 LIST_ENTRY *Link;\r
7936fb6a 2343 EFI_HANDLE NotifyHandle;\r
7936fb6a 2344 FORM_BROWSER_STATEMENT *Statement;\r
2345 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2346\r
5adb8db7 2347 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2348\r
2349 //\r
2350 // Register notify for Form package update\r
2351 //\r
2352 Status = mHiiDatabase->RegisterPackageNotify (\r
2353 mHiiDatabase,\r
8d00a0f1 2354 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2355 NULL,\r
2356 FormUpdateNotify,\r
2357 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2358 &NotifyHandle\r
2359 );\r
2360 if (EFI_ERROR (Status)) {\r
2361 return Status;\r
2362 }\r
2363\r
798e4d22
ED
2364 if ((Selection->Handle != mCurrentHiiHandle) ||\r
2365 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid))) {\r
2366 gFinishRetrieveCall = FALSE;\r
2367 }\r
2368\r
d66e6c16 2369 //\r
2370 // Initialize current settings of Questions in this FormSet\r
2371 //\r
7c6c064c 2372 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2373\r
2374 //\r
7c6c064c 2375 // Initilize Action field.\r
b9feb4bd 2376 //\r
7c6c064c
ED
2377 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2378\r
2379 //\r
2380 // Clean the mCurFakeQestId value is formset refreshed.\r
2381 //\r
2382 mCurFakeQestId = 0;\r
48a9d5f7 2383\r
7936fb6a 2384 do {\r
54f8fc6d
ED
2385 //\r
2386 // IFR is updated, force to reparse the IFR binary\r
2387 //\r
2388 if (mHiiPackageListUpdated) {\r
2389 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2390 mHiiPackageListUpdated = FALSE;\r
2391 break;\r
2392 }\r
2393\r
7936fb6a 2394 //\r
2395 // Initialize Selection->Form\r
2396 //\r
2397 if (Selection->FormId == 0) {\r
2398 //\r
2399 // Zero FormId indicates display the first Form in a FormSet\r
2400 //\r
2401 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2402\r
2403 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2404 Selection->FormId = Selection->Form->FormId;\r
2405 } else {\r
2406 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2407 }\r
2408\r
0a1147ed
LG
2409 if (Selection->Form == NULL) {\r
2410 //\r
2411 // No Form to display\r
2412 //\r
13ad1def
LG
2413 Status = EFI_NOT_FOUND;\r
2414 goto Done;\r
0a1147ed
LG
2415 }\r
2416\r
0c66bc76
LG
2417 //\r
2418 // Check Form is suppressed.\r
2419 //\r
2420 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2421 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2422 //\r
2423 // Form is suppressed. \r
2424 //\r
7c6c064c 2425 gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
13ad1def
LG
2426 Status = EFI_NOT_FOUND;\r
2427 goto Done;\r
0c66bc76
LG
2428 }\r
2429 }\r
5adb8db7 2430\r
5adb8db7
LG
2431 //\r
2432 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2433 // for each question with callback flag.\r
2434 // New form may be the first form, or the different form after another form close.\r
2435 //\r
70f1d5e7 2436 if (((Selection->Handle != mCurrentHiiHandle) ||\r
13ad1def
LG
2437 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2438 (Selection->FormId != mCurrentFormId))) {\r
13ad1def
LG
2439 //\r
2440 // Keep current form information\r
2441 //\r
2442 mCurrentHiiHandle = Selection->Handle;\r
2443 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2444 mCurrentFormId = Selection->FormId;\r
2445\r
70f1d5e7
ED
2446 if (ConfigAccess != NULL) {\r
2447 Status = ProcessCallBackFunction (Selection, gCurrentSelection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
2448 if (EFI_ERROR (Status)) {\r
2449 goto Done;\r
2450 }\r
b18e7050 2451\r
70f1d5e7
ED
2452 //\r
2453 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2454 //\r
2455 if (mHiiPackageListUpdated) {\r
2456 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2457 mHiiPackageListUpdated = FALSE;\r
2458 break;\r
2459 }\r
5adb8db7
LG
2460 }\r
2461 }\r
2462\r
7936fb6a 2463 //\r
2464 // Load Questions' Value for display\r
2465 //\r
eccfeab1 2466 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2467 if (EFI_ERROR (Status)) {\r
13ad1def 2468 goto Done;\r
7936fb6a 2469 }\r
2470\r
798e4d22
ED
2471 //\r
2472 // Finish call RETRIEVE callback for this formset.\r
2473 //\r
2474 gFinishRetrieveCall = TRUE;\r
2475\r
eccfeab1
LG
2476 //\r
2477 // IFR is updated during callback of read value, force to reparse the IFR binary\r
2478 //\r
2479 if (mHiiPackageListUpdated) {\r
2480 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2481 mHiiPackageListUpdated = FALSE;\r
6a05469c 2482 break;\r
eccfeab1
LG
2483 }\r
2484\r
7936fb6a 2485 //\r
2486 // Display form\r
2487 //\r
7c6c064c 2488 Status = DisplayForm ();\r
7936fb6a 2489 if (EFI_ERROR (Status)) {\r
13ad1def 2490 goto Done;\r
7936fb6a 2491 }\r
2492\r
2493 //\r
2494 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2495 //\r
2496 Statement = Selection->Statement;\r
2497 if (Statement != NULL) {\r
13ad1def
LG
2498 if ((ConfigAccess != NULL) && \r
2499 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2500 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2501 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2502 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2503 //\r
2504 // Process dynamic update ref opcode.\r
2505 //\r
2506 if (!EFI_ERROR (Status)) {\r
7c6c064c 2507 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2508 }\r
2509 \r
3dde743f 2510 //\r
8ca6180f 2511 // Callback return error status or status return from process goto opcode.\r
3dde743f 2512 //\r
8ca6180f 2513 if (EFI_ERROR (Status)) {\r
3dde743f 2514 //\r
2515 // Cross reference will not be taken\r
2516 //\r
2517 Selection->FormId = Selection->Form->FormId;\r
2518 Selection->QuestionId = 0;\r
2519 }\r
7936fb6a 2520 }\r
b7891584 2521\r
a6c0ad81
ED
2522 //\r
2523 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2524 //\r
2525 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2526\r
3a4e7a3e 2527 if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
798e4d22 2528 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
b7891584 2529 }\r
e6cc2ab3
ED
2530 } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
2531 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
a6c0ad81
ED
2532 //\r
2533 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2534 //\r
2535 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
7936fb6a 2536 }\r
892eccc8 2537\r
b1239a24
ED
2538 //\r
2539 // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
2540 // trig the gResetFlag.\r
2541 //\r
2542 if ((Status == EFI_SUCCESS) && \r
2543 (Statement->Storage == NULL) && \r
2544 ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2545 gResetRequired = TRUE;\r
2546 }\r
7936fb6a 2547 }\r
7936fb6a 2548\r
7c6c064c
ED
2549 //\r
2550 // Check whether Exit flag is TRUE.\r
2551 //\r
2552 if (gExitRequired) {\r
2553 switch (gBrowserSettingScope) {\r
2554 case SystemLevel:\r
2555 Selection->Action = UI_ACTION_EXIT;\r
2556 break;\r
2557\r
2558 case FormSetLevel:\r
2559 case FormLevel:\r
2560 FindNextMenu (Selection, gBrowserSettingScope);\r
2561 break;\r
2562\r
2563 default:\r
2564 break;\r
2565 }\r
2566\r
2567 gExitRequired = FALSE;\r
2568 }\r
2569\r
5adb8db7
LG
2570 //\r
2571 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2572 // for each question with callback flag.\r
2573 //\r
5adb8db7
LG
2574 if ((ConfigAccess != NULL) && \r
2575 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2576 (Selection->Handle != mCurrentHiiHandle) ||\r
2577 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2578 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2579\r
798e4d22 2580 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2581 if (EFI_ERROR (Status)) {\r
2582 goto Done;\r
f4a2af1f 2583 }\r
2584 }\r
5adb8db7 2585 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2586\r
d66e6c16 2587Done:\r
13ad1def
LG
2588 //\r
2589 // Reset current form information to the initial setting when error happens or form exit.\r
2590 //\r
2591 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2592 mCurrentHiiHandle = NULL;\r
2593 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2594 mCurrentFormId = 0;\r
2595 }\r
2596\r
7936fb6a 2597 //\r
2598 // Unregister notify for Form package update\r
2599 //\r
13ad1def
LG
2600 mHiiDatabase->UnregisterPackageNotify (\r
2601 mHiiDatabase,\r
2602 NotifyHandle\r
2603 );\r
7936fb6a 2604 return Status;\r
2605}\r