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