]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Sync value for string opcode after call the Callback 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
061d5462 2095 CHAR16 *NewString;\r
b18e7050 2096\r
798e4d22 2097 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 2098 SubmitFormIsRequired = FALSE;\r
48a9d5f7 2099 SettingLevel = FormSetLevel;\r
b18e7050
ED
2100 DiscardFormIsRequired = FALSE;\r
2101 NeedExit = FALSE;\r
2102 Status = EFI_SUCCESS;\r
2103 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 2104 BackUpBuffer = NULL;\r
b18e7050
ED
2105\r
2106 if (ConfigAccess == NULL) {\r
2107 return EFI_SUCCESS;\r
2108 }\r
2109\r
798e4d22
ED
2110 Link = GetFirstNode (&Form->StatementListHead);\r
2111 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 2112 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 2113 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
2114\r
2115 //\r
2116 // if Question != NULL, only process the question. Else, process all question in this form.\r
2117 //\r
2118 if ((Question != NULL) && (Statement != Question)) {\r
2119 continue;\r
2120 }\r
2121 \r
2122 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2123 continue;\r
2124 }\r
2125\r
2126 //\r
2127 // Check whether Statement is disabled.\r
2128 //\r
31585af4 2129 if (Statement->Expression != NULL) {\r
798e4d22 2130 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
2131 continue;\r
2132 }\r
2133 }\r
2134\r
2135 HiiValue = &Statement->HiiValue;\r
2136 TypeValue = &HiiValue->Value;\r
2137 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2138 //\r
2139 // For OrderedList, passing in the value buffer to Callback()\r
2140 //\r
2141 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2142 }\r
e6cc2ab3
ED
2143\r
2144 //\r
2145 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
2146 //\r
2147 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2148 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2149 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
2150 } else {\r
2151 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
2152 }\r
2153 }\r
2154\r
b18e7050
ED
2155 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2156 Status = ConfigAccess->Callback (\r
2157 ConfigAccess,\r
2158 Action,\r
2159 Statement->QuestionId,\r
2160 HiiValue->Type,\r
2161 TypeValue,\r
2162 &ActionRequest\r
2163 );\r
2164 if (!EFI_ERROR (Status)) {\r
3a4e7a3e
ED
2165 //\r
2166 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
2167 //\r
2168 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2169 switch (ActionRequest) {\r
2170 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 2171 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 2172 gResetRequired = TRUE;\r
7c6c064c 2173 NeedExit = TRUE;\r
3a4e7a3e 2174 break;\r
b18e7050 2175\r
3a4e7a3e
ED
2176 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2177 SubmitFormIsRequired = TRUE;\r
7c6c064c 2178 NeedExit = TRUE;\r
3a4e7a3e 2179 break;\r
b18e7050 2180\r
3a4e7a3e 2181 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 2182 DiscardFormIsRequired = TRUE;\r
7c6c064c 2183 NeedExit = TRUE;\r
3a4e7a3e 2184 break;\r
b18e7050 2185\r
3a4e7a3e
ED
2186 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
2187 SubmitFormIsRequired = TRUE;\r
2188 SettingLevel = FormLevel;\r
2189 NeedExit = TRUE;\r
2190 break;\r
b18e7050 2191\r
3a4e7a3e
ED
2192 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
2193 DiscardFormIsRequired = TRUE;\r
7c6c064c 2194 SettingLevel = FormLevel;\r
3a4e7a3e
ED
2195 NeedExit = TRUE;\r
2196 break;\r
b18e7050 2197\r
3a4e7a3e
ED
2198 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
2199 SubmitFormIsRequired = TRUE;\r
2200 SettingLevel = FormLevel;\r
2201 break;\r
b18e7050 2202\r
3a4e7a3e
ED
2203 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
2204 DiscardFormIsRequired = TRUE;\r
2205 SettingLevel = FormLevel;\r
2206 break;\r
b18e7050 2207\r
3a4e7a3e
ED
2208 default:\r
2209 break;\r
2210 }\r
b18e7050 2211 }\r
8ca6180f 2212\r
061d5462
ED
2213 //\r
2214 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
2215 //\r
2216 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2217 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2218 ASSERT (NewString != NULL);\r
2219\r
2220 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2221 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2222 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2223 } else {\r
2224 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2225 }\r
2226 FreePool (NewString);\r
2227 }\r
2228\r
8ca6180f
ED
2229 //\r
2230 // According the spec, return value from call back of "changing" and \r
2231 // "retrieve" should update to the question's temp buffer.\r
2232 //\r
2233 if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2234 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
8ca6180f 2235 }\r
c4042207 2236 } else {\r
e6cc2ab3
ED
2237 //\r
2238 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2239 // then the browser will use the value passed to Callback() and ignore the \r
2240 // value returned by Callback(). \r
2241 //\r
2242 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2243 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2244 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2245 } else {\r
2246 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2247 }\r
2248\r
798e4d22 2249 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
e6cc2ab3
ED
2250 }\r
2251\r
b18e7050 2252 //\r
c4042207
ED
2253 // According the spec, return fail from call back of "changing" and \r
2254 // "retrieve", should restore the question's value.\r
b18e7050 2255 //\r
e6cc2ab3
ED
2256 if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || \r
2257 Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2258 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2259 }\r
2260\r
2261 if (Status == EFI_UNSUPPORTED) {\r
2262 //\r
2263 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2264 //\r
2265 Status = EFI_SUCCESS;\r
2266 }\r
b18e7050 2267 }\r
e6cc2ab3
ED
2268\r
2269 if (BackUpBuffer != NULL) {\r
2270 FreePool (BackUpBuffer);\r
2271 }\r
b18e7050
ED
2272 }\r
2273\r
2274 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2275 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2276 }\r
2277\r
2278 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2279 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2280 }\r
2281\r
2282 if (NeedExit) {\r
7c6c064c 2283 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2284 }\r
2285\r
2286 return Status;\r
2287}\r
2288\r
9776099f
ED
2289/**\r
2290 Call the retrieve type call back function for one question to get the initialize data.\r
2291 \r
2292 This function only used when in the initialize stage, because in this stage, the \r
2293 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2294\r
2295 @param ConfigAccess The config access protocol produced by the hii driver.\r
2296 @param Statement The Question which need to call.\r
061d5462 2297 @param FormSet The formset this question belong to.\r
9776099f
ED
2298\r
2299 @retval EFI_SUCCESS The call back function excutes successfully.\r
2300 @return Other value if the call back function failed to excute. \r
2301**/\r
2302EFI_STATUS \r
2303ProcessRetrieveForQuestion (\r
2304 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
061d5462
ED
2305 IN FORM_BROWSER_STATEMENT *Statement,\r
2306 IN FORM_BROWSER_FORMSET *FormSet\r
9776099f
ED
2307 )\r
2308{\r
2309 EFI_STATUS Status;\r
2310 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2311 EFI_HII_VALUE *HiiValue;\r
2312 EFI_IFR_TYPE_VALUE *TypeValue;\r
061d5462 2313 CHAR16 *NewString;\r
9776099f
ED
2314\r
2315 Status = EFI_SUCCESS;\r
2316 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
70f1d5e7
ED
2317\r
2318 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
9776099f
ED
2319 return EFI_UNSUPPORTED;\r
2320 }\r
2321\r
2322 HiiValue = &Statement->HiiValue;\r
2323 TypeValue = &HiiValue->Value;\r
2324 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2325 //\r
2326 // For OrderedList, passing in the value buffer to Callback()\r
2327 //\r
2328 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2329 }\r
2330 \r
2331 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2332 Status = ConfigAccess->Callback (\r
2333 ConfigAccess,\r
2334 EFI_BROWSER_ACTION_RETRIEVE,\r
2335 Statement->QuestionId,\r
2336 HiiValue->Type,\r
2337 TypeValue,\r
2338 &ActionRequest\r
2339 );\r
061d5462
ED
2340 if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2341 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2342 ASSERT (NewString != NULL);\r
2343\r
2344 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2345 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2346 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2347 } else {\r
2348 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2349 }\r
2350 FreePool (NewString);\r
2351 }\r
2352\r
9776099f
ED
2353 return Status;\r
2354}\r
2355\r
7936fb6a 2356/**\r
2357 The worker function that send the displays to the screen. On output,\r
2358 the selection made by user is returned.\r
2359\r
2360 @param Selection On input, Selection tell setup browser the information\r
2361 about the Selection, form and formset to be displayed.\r
2362 On output, Selection return the screen item that is selected\r
2363 by user.\r
2364\r
2365 @retval EFI_SUCCESS The page is displayed successfully.\r
2366 @return Other value if the page failed to be diplayed.\r
2367\r
2368**/\r
2369EFI_STATUS\r
2370SetupBrowser (\r
2371 IN OUT UI_MENU_SELECTION *Selection\r
2372 )\r
2373{\r
2374 EFI_STATUS Status;\r
2375 LIST_ENTRY *Link;\r
7936fb6a 2376 EFI_HANDLE NotifyHandle;\r
7936fb6a 2377 FORM_BROWSER_STATEMENT *Statement;\r
2378 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2379\r
5adb8db7 2380 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2381\r
2382 //\r
2383 // Register notify for Form package update\r
2384 //\r
2385 Status = mHiiDatabase->RegisterPackageNotify (\r
2386 mHiiDatabase,\r
8d00a0f1 2387 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2388 NULL,\r
2389 FormUpdateNotify,\r
2390 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2391 &NotifyHandle\r
2392 );\r
2393 if (EFI_ERROR (Status)) {\r
2394 return Status;\r
2395 }\r
2396\r
798e4d22
ED
2397 if ((Selection->Handle != mCurrentHiiHandle) ||\r
2398 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid))) {\r
2399 gFinishRetrieveCall = FALSE;\r
2400 }\r
2401\r
d66e6c16 2402 //\r
2403 // Initialize current settings of Questions in this FormSet\r
2404 //\r
7c6c064c 2405 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2406\r
2407 //\r
7c6c064c 2408 // Initilize Action field.\r
b9feb4bd 2409 //\r
7c6c064c
ED
2410 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2411\r
2412 //\r
2413 // Clean the mCurFakeQestId value is formset refreshed.\r
2414 //\r
2415 mCurFakeQestId = 0;\r
48a9d5f7 2416\r
7936fb6a 2417 do {\r
54f8fc6d
ED
2418 //\r
2419 // IFR is updated, force to reparse the IFR binary\r
2420 //\r
2421 if (mHiiPackageListUpdated) {\r
2422 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2423 mHiiPackageListUpdated = FALSE;\r
2424 break;\r
2425 }\r
2426\r
7936fb6a 2427 //\r
2428 // Initialize Selection->Form\r
2429 //\r
2430 if (Selection->FormId == 0) {\r
2431 //\r
2432 // Zero FormId indicates display the first Form in a FormSet\r
2433 //\r
2434 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2435\r
2436 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2437 Selection->FormId = Selection->Form->FormId;\r
2438 } else {\r
2439 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2440 }\r
2441\r
0a1147ed
LG
2442 if (Selection->Form == NULL) {\r
2443 //\r
2444 // No Form to display\r
2445 //\r
13ad1def
LG
2446 Status = EFI_NOT_FOUND;\r
2447 goto Done;\r
0a1147ed
LG
2448 }\r
2449\r
0c66bc76
LG
2450 //\r
2451 // Check Form is suppressed.\r
2452 //\r
2453 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2454 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2455 //\r
2456 // Form is suppressed. \r
2457 //\r
7c6c064c 2458 gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
13ad1def
LG
2459 Status = EFI_NOT_FOUND;\r
2460 goto Done;\r
0c66bc76
LG
2461 }\r
2462 }\r
5adb8db7 2463\r
5adb8db7
LG
2464 //\r
2465 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2466 // for each question with callback flag.\r
2467 // New form may be the first form, or the different form after another form close.\r
2468 //\r
70f1d5e7 2469 if (((Selection->Handle != mCurrentHiiHandle) ||\r
13ad1def
LG
2470 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2471 (Selection->FormId != mCurrentFormId))) {\r
13ad1def
LG
2472 //\r
2473 // Keep current form information\r
2474 //\r
2475 mCurrentHiiHandle = Selection->Handle;\r
2476 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2477 mCurrentFormId = Selection->FormId;\r
2478\r
70f1d5e7
ED
2479 if (ConfigAccess != NULL) {\r
2480 Status = ProcessCallBackFunction (Selection, gCurrentSelection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
2481 if (EFI_ERROR (Status)) {\r
2482 goto Done;\r
2483 }\r
b18e7050 2484\r
70f1d5e7
ED
2485 //\r
2486 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2487 //\r
2488 if (mHiiPackageListUpdated) {\r
2489 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2490 mHiiPackageListUpdated = FALSE;\r
2491 break;\r
2492 }\r
5adb8db7
LG
2493 }\r
2494 }\r
2495\r
7936fb6a 2496 //\r
2497 // Load Questions' Value for display\r
2498 //\r
eccfeab1 2499 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2500 if (EFI_ERROR (Status)) {\r
13ad1def 2501 goto Done;\r
7936fb6a 2502 }\r
2503\r
798e4d22
ED
2504 //\r
2505 // Finish call RETRIEVE callback for this formset.\r
2506 //\r
2507 gFinishRetrieveCall = TRUE;\r
2508\r
eccfeab1
LG
2509 //\r
2510 // IFR is updated during callback of read value, force to reparse the IFR binary\r
2511 //\r
2512 if (mHiiPackageListUpdated) {\r
2513 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2514 mHiiPackageListUpdated = FALSE;\r
6a05469c 2515 break;\r
eccfeab1
LG
2516 }\r
2517\r
7936fb6a 2518 //\r
2519 // Display form\r
2520 //\r
7c6c064c 2521 Status = DisplayForm ();\r
7936fb6a 2522 if (EFI_ERROR (Status)) {\r
13ad1def 2523 goto Done;\r
7936fb6a 2524 }\r
2525\r
2526 //\r
2527 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2528 //\r
2529 Statement = Selection->Statement;\r
2530 if (Statement != NULL) {\r
13ad1def
LG
2531 if ((ConfigAccess != NULL) && \r
2532 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2533 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2534 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2535 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2536 //\r
2537 // Process dynamic update ref opcode.\r
2538 //\r
2539 if (!EFI_ERROR (Status)) {\r
7c6c064c 2540 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2541 }\r
2542 \r
3dde743f 2543 //\r
8ca6180f 2544 // Callback return error status or status return from process goto opcode.\r
3dde743f 2545 //\r
8ca6180f 2546 if (EFI_ERROR (Status)) {\r
3dde743f 2547 //\r
2548 // Cross reference will not be taken\r
2549 //\r
2550 Selection->FormId = Selection->Form->FormId;\r
2551 Selection->QuestionId = 0;\r
2552 }\r
7936fb6a 2553 }\r
b7891584 2554\r
a6c0ad81
ED
2555 //\r
2556 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2557 //\r
2558 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2559\r
3a4e7a3e 2560 if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
798e4d22 2561 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
b7891584 2562 }\r
e6cc2ab3
ED
2563 } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
2564 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
a6c0ad81
ED
2565 //\r
2566 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2567 //\r
2568 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
7936fb6a 2569 }\r
892eccc8 2570\r
b1239a24
ED
2571 //\r
2572 // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
2573 // trig the gResetFlag.\r
2574 //\r
2575 if ((Status == EFI_SUCCESS) && \r
2576 (Statement->Storage == NULL) && \r
2577 ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2578 gResetRequired = TRUE;\r
2579 }\r
7936fb6a 2580 }\r
7936fb6a 2581\r
7c6c064c
ED
2582 //\r
2583 // Check whether Exit flag is TRUE.\r
2584 //\r
2585 if (gExitRequired) {\r
2586 switch (gBrowserSettingScope) {\r
2587 case SystemLevel:\r
2588 Selection->Action = UI_ACTION_EXIT;\r
2589 break;\r
2590\r
2591 case FormSetLevel:\r
2592 case FormLevel:\r
2593 FindNextMenu (Selection, gBrowserSettingScope);\r
2594 break;\r
2595\r
2596 default:\r
2597 break;\r
2598 }\r
2599\r
2600 gExitRequired = FALSE;\r
2601 }\r
2602\r
5adb8db7
LG
2603 //\r
2604 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2605 // for each question with callback flag.\r
2606 //\r
5adb8db7
LG
2607 if ((ConfigAccess != NULL) && \r
2608 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2609 (Selection->Handle != mCurrentHiiHandle) ||\r
2610 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2611 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2612\r
798e4d22 2613 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2614 if (EFI_ERROR (Status)) {\r
2615 goto Done;\r
f4a2af1f 2616 }\r
2617 }\r
5adb8db7 2618 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2619\r
d66e6c16 2620Done:\r
13ad1def
LG
2621 //\r
2622 // Reset current form information to the initial setting when error happens or form exit.\r
2623 //\r
2624 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2625 mCurrentHiiHandle = NULL;\r
2626 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2627 mCurrentFormId = 0;\r
2628 }\r
2629\r
7936fb6a 2630 //\r
2631 // Unregister notify for Form package update\r
2632 //\r
13ad1def
LG
2633 mHiiDatabase->UnregisterPackageNotify (\r
2634 mHiiDatabase,\r
2635 NotifyHandle\r
2636 );\r
7936fb6a 2637 return Status;\r
2638}\r