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