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