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