]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Update the logic for action opcode, also support user input a empty string for Questi...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for UI presentation.\r
3\r
c792e5b8 4Copyright (c) 2004 - 2015, 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
787fc2a6 931 ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, 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
40ad4b1a
ED
1429 } else if (ConfigResp[0] == L'\0') {\r
1430 return EFI_SUCCESS;\r
7c6c064c 1431 }\r
7936fb6a 1432\r
7c6c064c
ED
1433 //\r
1434 // Send config to Configuration Driver\r
1435 //\r
7248790e
ED
1436 Status = mHiiConfigRouting->RouteConfig (\r
1437 mHiiConfigRouting,\r
7c6c064c
ED
1438 ConfigResp,\r
1439 &Progress\r
1440 );\r
7936fb6a 1441\r
7c6c064c 1442 return Status;\r
7936fb6a 1443}\r
1444\r
7936fb6a 1445/**\r
1446\r
7c6c064c 1447 Process the user input data.\r
d66e6c16 1448\r
7c6c064c 1449 @param UserInput The user input data.\r
d66e6c16 1450\r
7936fb6a 1451 @retval EFI_SUCESSS This function always return successfully for now.\r
1452\r
1453**/\r
1454EFI_STATUS\r
7c6c064c 1455ProcessUserInput (\r
42645c3d 1456 IN USER_INPUT *UserInput\r
7936fb6a 1457 )\r
1458{\r
7c6c064c
ED
1459 EFI_STATUS Status;\r
1460 FORM_BROWSER_STATEMENT *Statement;\r
25361615 1461\r
42645c3d
ED
1462 Status = EFI_SUCCESS;\r
1463 Statement = NULL;\r
7936fb6a 1464\r
1465 //\r
7c6c064c 1466 // When Exit from FormDisplay function, one of the below two cases must be true.\r
7936fb6a 1467 //\r
7c6c064c 1468 ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
7936fb6a 1469\r
b9feb4bd 1470 //\r
7c6c064c 1471 // Remove the last highligh question id, this id will update when show next form.\r
b9feb4bd 1472 //\r
7c6c064c 1473 gCurrentSelection->QuestionId = 0;\r
42645c3d
ED
1474 if (UserInput->SelectedStatement != NULL){\r
1475 Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
1476 ASSERT (Statement != NULL);\r
1477\r
1478 //\r
1479 // This question is the current user select one,record it and later\r
1480 // show it as the highlight question.\r
1481 //\r
1482 gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
1483 //\r
1484 // For statement like text, actio, it not has question id.\r
1485 // So use FakeQuestionId to save the question.\r
1486 //\r
1487 if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
1488 mCurFakeQestId = Statement->FakeQuestionId;\r
1489 } else {\r
1490 mCurFakeQestId = 0;\r
1491 }\r
1492 }\r
7936fb6a 1493\r
7c6c064c
ED
1494 //\r
1495 // First process the Action field in USER_INPUT.\r
1496 //\r
1497 if (UserInput->Action != 0) {\r
1498 Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
7c6c064c 1499 gCurrentSelection->Statement = NULL;\r
7c6c064c 1500 } else {\r
7c6c064c 1501 ASSERT (Statement != NULL);\r
7c6c064c 1502 gCurrentSelection->Statement = Statement;\r
7c6c064c
ED
1503 switch (Statement->Operand) {\r
1504 case EFI_IFR_REF_OP:\r
1505 Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
1506 break;\r
1507 \r
1508 case EFI_IFR_ACTION_OP:\r
1509 //\r
1510 // Process the Config string <ConfigResp>\r
1511 //\r
1512 Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
1513 break;\r
1514 \r
1515 case EFI_IFR_RESET_BUTTON_OP:\r
7936fb6a 1516 //\r
7c6c064c 1517 // Reset Question to default value specified by DefaultId\r
7936fb6a 1518 //\r
787fc2a6 1519 Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
892eccc8 1520 UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
7c6c064c
ED
1521 break;\r
1522\r
1523 default:\r
1524 switch (Statement->Operand) {\r
1525 case EFI_IFR_STRING_OP:\r
1526 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1527 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1528 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1529 FreePool (UserInput->InputValue.Buffer);\r
1530 break;\r
1531\r
1532 case EFI_IFR_PASSWORD_OP:\r
1533 if (UserInput->InputValue.Buffer == NULL) {\r
1534 //\r
1535 // User not input new password, just return.\r
1536 //\r
1537 break;\r
1538 }\r
8b0fc5c1 1539\r
7c6c064c
ED
1540 DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
1541 Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
1542 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
1543 FreePool (UserInput->InputValue.Buffer);\r
8b0fc5c1 1544 //\r
7c6c064c 1545 // Two password match, send it to Configuration Driver\r
8b0fc5c1 1546 //\r
7c6c064c
ED
1547 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
1548 PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
1549 //\r
1550 // Clean the value after saved it.\r
1551 //\r
1552 ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
1553 HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
1554 } else {\r
1555 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
1556 }\r
1557 break;\r
1558\r
1559 case EFI_IFR_ORDERED_LIST_OP:\r
1560 CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
1561 break;\r
1562\r
1563 default:\r
1564 CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
1565 break;\r
1566 }\r
7c6c064c 1567 break;\r
7936fb6a 1568 }\r
7936fb6a 1569 }\r
1570\r
7936fb6a 1571 return Status;\r
1572}\r
1573\r
1574/**\r
7936fb6a 1575\r
7c6c064c 1576 Display form and wait for user to select one menu option, then return it.\r
7936fb6a 1577\r
7c6c064c 1578 @retval EFI_SUCESSS This function always return successfully for now.\r
48a9d5f7
LG
1579\r
1580**/\r
7c6c064c
ED
1581EFI_STATUS\r
1582DisplayForm (\r
48a9d5f7
LG
1583 VOID\r
1584 )\r
1585{\r
7c6c064c
ED
1586 EFI_STATUS Status;\r
1587 USER_INPUT UserInput;\r
1588 FORM_ENTRY_INFO *CurrentMenu;\r
48a9d5f7 1589\r
7c6c064c 1590 ZeroMem (&UserInput, sizeof (USER_INPUT));\r
48a9d5f7
LG
1591\r
1592 //\r
7c6c064c 1593 // Update the menu history data.\r
48a9d5f7 1594 //\r
7c6c064c
ED
1595 CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
1596 if (CurrentMenu == NULL) {\r
48a9d5f7 1597 //\r
7c6c064c 1598 // Current menu not found, add it to the menu tree\r
25361615 1599 //\r
7c6c064c
ED
1600 CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
1601 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
1602 ASSERT (CurrentMenu != NULL);\r
1603 }\r
4d4deaac
ED
1604\r
1605 //\r
1606 // Back up the form view history data for this form.\r
1607 //\r
1608 UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
1609\r
7c6c064c 1610 gCurrentSelection->CurrentMenu = CurrentMenu;\r
48a9d5f7 1611\r
7c6c064c 1612 if (gCurrentSelection->QuestionId == 0) {\r
48a9d5f7 1613 //\r
7c6c064c 1614 // Highlight not specified, fetch it from cached menu\r
48a9d5f7 1615 //\r
7c6c064c 1616 gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
48a9d5f7 1617 }\r
25361615 1618\r
7c6c064c
ED
1619 Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
1620 if (EFI_ERROR (Status)) {\r
1621 return Status;\r
b9feb4bd 1622 }\r
7936fb6a 1623\r
7c6c064c 1624 UpdateDisplayFormData ();\r
25361615 1625\r
4d4deaac 1626 ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
7c6c064c 1627 Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
42645c3d 1628 if (EFI_ERROR (Status)) {\r
7c6c064c
ED
1629 FreeDisplayFormData();\r
1630 return Status;\r
1631 }\r
25361615 1632\r
42645c3d 1633 Status = ProcessUserInput (&UserInput);\r
7c6c064c 1634 FreeDisplayFormData();\r
7c6c064c 1635 return Status;\r
7936fb6a 1636}\r
1637\r
1638/**\r
1639 Functions which are registered to receive notification of\r
1640 database events have this prototype. The actual event is encoded\r
1641 in NotifyType. The following table describes how PackageType,\r
1642 PackageGuid, Handle, and Package are used for each of the\r
1643 notification types.\r
1644\r
1645 @param PackageType Package type of the notification.\r
1646\r
1647 @param PackageGuid If PackageType is\r
1648 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
1649 the pointer to the GUID from the Guid\r
1650 field of EFI_HII_PACKAGE_GUID_HEADER.\r
1651 Otherwise, it must be NULL.\r
1652\r
1653 @param Package Points to the package referred to by the\r
1654 notification Handle The handle of the package\r
1655 list which contains the specified package.\r
1656\r
1657 @param Handle The HII handle.\r
1658\r
1659 @param NotifyType The type of change concerning the\r
1660 database. See\r
1661 EFI_HII_DATABASE_NOTIFY_TYPE.\r
1662\r
1663**/\r
1664EFI_STATUS\r
6d3ea23f 1665EFIAPI\r
7936fb6a 1666FormUpdateNotify (\r
1667 IN UINT8 PackageType,\r
1668 IN CONST EFI_GUID *PackageGuid,\r
1669 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
1670 IN EFI_HII_HANDLE Handle,\r
1671 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
1672 )\r
1673{\r
1674 mHiiPackageListUpdated = TRUE;\r
1675\r
1676 return EFI_SUCCESS;\r
1677}\r
1678\r
b18e7050 1679/**\r
7c6c064c 1680 Update the NV flag info for this form set.\r
b18e7050
ED
1681\r
1682 @param FormSet FormSet data structure.\r
1683\r
b18e7050 1684**/\r
7c6c064c
ED
1685BOOLEAN\r
1686IsNvUpdateRequiredForFormSet (\r
b18e7050
ED
1687 IN FORM_BROWSER_FORMSET *FormSet\r
1688 )\r
1689{\r
1690 LIST_ENTRY *Link;\r
1691 FORM_BROWSER_FORM *Form;\r
7c6c064c
ED
1692 BOOLEAN RetVal;\r
1693\r
1694 //\r
1695 // Not finished question initialization, return FALSE.\r
1696 //\r
1697 if (!FormSet->QuestionInited) {\r
1698 return FALSE;\r
1699 }\r
1700\r
1701 RetVal = FALSE;\r
b18e7050
ED
1702\r
1703 Link = GetFirstNode (&FormSet->FormListHead);\r
1704 while (!IsNull (&FormSet->FormListHead, Link)) {\r
1705 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
1706\r
7c6c064c
ED
1707 RetVal = IsNvUpdateRequiredForForm(Form);\r
1708 if (RetVal) {\r
1709 break;\r
b9feb4bd
ED
1710 }\r
1711\r
25361615 1712 Link = GetNextNode (&FormSet->FormListHead, Link);\r
b9feb4bd
ED
1713 }\r
1714\r
7c6c064c
ED
1715 return RetVal;\r
1716}\r
1717\r
1718/**\r
1719 Update the NvUpdateRequired flag for a form.\r
1720\r
1721 @param Form Form data structure.\r
1722\r
1723**/\r
1724BOOLEAN\r
1725IsNvUpdateRequiredForForm (\r
1726 IN FORM_BROWSER_FORM *Form\r
1727 )\r
1728{\r
1729 LIST_ENTRY *Link;\r
1730 FORM_BROWSER_STATEMENT *Statement;\r
1731\r
1732 Link = GetFirstNode (&Form->StatementListHead);\r
1733 while (!IsNull (&Form->StatementListHead, Link)) {\r
1734 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1735\r
1736 if (Statement->ValueChanged) {\r
1737 return TRUE;\r
1738 }\r
1739\r
1740 Link = GetNextNode (&Form->StatementListHead, Link);\r
1741 }\r
1742\r
b18e7050
ED
1743 return FALSE;\r
1744}\r
1745\r
b18e7050
ED
1746/**\r
1747 Find menu which will show next time.\r
1748\r
1749 @param Selection On input, Selection tell setup browser the information\r
1750 about the Selection, form and formset to be displayed.\r
1751 On output, Selection return the screen item that is selected\r
1752 by user.\r
7c6c064c
ED
1753 @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
1754 else, we need to exit current formset.\r
b18e7050 1755 \r
7c6c064c
ED
1756 @retval TRUE Exit current form.\r
1757 @retval FALSE User press ESC and keep in current form.\r
b18e7050
ED
1758**/\r
1759BOOLEAN\r
1760FindNextMenu (\r
7c6c064c 1761 IN OUT UI_MENU_SELECTION *Selection,\r
93551a01 1762 IN BROWSER_SETTING_SCOPE SettingLevel\r
b18e7050
ED
1763 )\r
1764{\r
7c6c064c
ED
1765 FORM_ENTRY_INFO *CurrentMenu;\r
1766 FORM_ENTRY_INFO *ParentMenu;\r
1767 BROWSER_SETTING_SCOPE Scope;\r
b18e7050
ED
1768 \r
1769 CurrentMenu = Selection->CurrentMenu;\r
7c6c064c 1770 Scope = FormSetLevel;\r
b18e7050 1771\r
93551a01
ED
1772 ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
1773 while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
1774 ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
1775 }\r
25361615 1776\r
93551a01
ED
1777 if (ParentMenu != NULL) {\r
1778 if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
1779 Scope = FormLevel;\r
7c6c064c
ED
1780 } else {\r
1781 Scope = FormSetLevel;\r
b18e7050 1782 }\r
25361615
ED
1783 }\r
1784\r
b9feb4bd 1785 //\r
7c6c064c 1786 // Form Level Check whether the data is changed.\r
b9feb4bd 1787 //\r
7c6c064c
ED
1788 if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
1789 (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
4d4deaac 1790 if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
25361615
ED
1791 return FALSE;\r
1792 }\r
7c6c064c 1793 }\r
b9feb4bd 1794\r
7c6c064c
ED
1795 if (ParentMenu != NULL) {\r
1796 //\r
1797 // ParentMenu is found. Then, go to it.\r
1798 //\r
1799 if (Scope == FormLevel) {\r
1800 Selection->Action = UI_ACTION_REFRESH_FORM;\r
25361615 1801 } else {\r
7c6c064c
ED
1802 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1803 CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
1804 Selection->Handle = ParentMenu->HiiHandle;\r
25361615 1805 }\r
25361615 1806\r
7c6c064c
ED
1807 Selection->Statement = NULL;\r
1808\r
1809 Selection->FormId = ParentMenu->FormId;\r
1810 Selection->QuestionId = ParentMenu->QuestionId;\r
1811\r
1812 //\r
1813 // Clear highlight record for this menu\r
1814 //\r
25361615 1815 CurrentMenu->QuestionId = 0;\r
7c6c064c 1816 return FALSE;\r
25361615
ED
1817 }\r
1818\r
7c6c064c
ED
1819 //\r
1820 // Current in root page, exit the SendForm\r
1821 //\r
25361615 1822 Selection->Action = UI_ACTION_EXIT;\r
7c6c064c 1823\r
b18e7050
ED
1824 return TRUE;\r
1825}\r
1826\r
1827/**\r
1828 Call the call back function for the question and process the return action.\r
1829\r
1830 @param Selection On input, Selection tell setup browser the information\r
1831 about the Selection, form and formset to be displayed.\r
1832 On output, Selection return the screen item that is selected\r
1833 by user.\r
798e4d22
ED
1834 @param FormSet The formset this question belong to.\r
1835 @param Form The form this question belong to.\r
b18e7050
ED
1836 @param Question The Question which need to call.\r
1837 @param Action The action request.\r
1838 @param SkipSaveOrDiscard Whether skip save or discard action.\r
1839\r
1840 @retval EFI_SUCCESS The call back function excutes successfully.\r
1841 @return Other value if the call back function failed to excute. \r
1842**/\r
1843EFI_STATUS \r
1844ProcessCallBackFunction (\r
1845 IN OUT UI_MENU_SELECTION *Selection,\r
798e4d22
ED
1846 IN FORM_BROWSER_FORMSET *FormSet,\r
1847 IN FORM_BROWSER_FORM *Form,\r
b18e7050
ED
1848 IN FORM_BROWSER_STATEMENT *Question,\r
1849 IN EFI_BROWSER_ACTION Action,\r
1850 IN BOOLEAN SkipSaveOrDiscard\r
1851 )\r
1852{\r
1853 EFI_STATUS Status;\r
fc2e7502 1854 EFI_STATUS InternalStatus;\r
b18e7050
ED
1855 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
1856 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1857 EFI_HII_VALUE *HiiValue;\r
1858 EFI_IFR_TYPE_VALUE *TypeValue;\r
1859 FORM_BROWSER_STATEMENT *Statement;\r
1860 BOOLEAN SubmitFormIsRequired;\r
b18e7050
ED
1861 BOOLEAN DiscardFormIsRequired;\r
1862 BOOLEAN NeedExit;\r
1863 LIST_ENTRY *Link;\r
48a9d5f7 1864 BROWSER_SETTING_SCOPE SettingLevel;\r
e6cc2ab3
ED
1865 EFI_IFR_TYPE_VALUE BackUpValue;\r
1866 UINT8 *BackUpBuffer;\r
061d5462 1867 CHAR16 *NewString;\r
b18e7050 1868\r
798e4d22 1869 ConfigAccess = FormSet->ConfigAccess;\r
b18e7050 1870 SubmitFormIsRequired = FALSE;\r
48a9d5f7 1871 SettingLevel = FormSetLevel;\r
b18e7050
ED
1872 DiscardFormIsRequired = FALSE;\r
1873 NeedExit = FALSE;\r
1874 Status = EFI_SUCCESS;\r
1875 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
e6cc2ab3 1876 BackUpBuffer = NULL;\r
b18e7050
ED
1877\r
1878 if (ConfigAccess == NULL) {\r
1879 return EFI_SUCCESS;\r
1880 }\r
1881\r
798e4d22
ED
1882 Link = GetFirstNode (&Form->StatementListHead);\r
1883 while (!IsNull (&Form->StatementListHead, Link)) {\r
b18e7050 1884 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
798e4d22 1885 Link = GetNextNode (&Form->StatementListHead, Link);\r
b18e7050
ED
1886\r
1887 //\r
1888 // if Question != NULL, only process the question. Else, process all question in this form.\r
1889 //\r
1890 if ((Question != NULL) && (Statement != Question)) {\r
1891 continue;\r
1892 }\r
1893 \r
1894 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
1895 continue;\r
1896 }\r
1897\r
1898 //\r
1899 // Check whether Statement is disabled.\r
1900 //\r
31585af4 1901 if (Statement->Expression != NULL) {\r
798e4d22 1902 if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
b18e7050
ED
1903 continue;\r
1904 }\r
1905 }\r
1906\r
1907 HiiValue = &Statement->HiiValue;\r
1908 TypeValue = &HiiValue->Value;\r
1909 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
1910 //\r
1911 // For OrderedList, passing in the value buffer to Callback()\r
1912 //\r
1913 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
1914 }\r
e6cc2ab3
ED
1915\r
1916 //\r
1917 // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
1918 //\r
1919 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
1920 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
1921 BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
523f48e7 1922 ASSERT (BackUpBuffer != NULL);\r
e6cc2ab3
ED
1923 } else {\r
1924 CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
1925 }\r
1926 }\r
1927\r
b18e7050
ED
1928 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1929 Status = ConfigAccess->Callback (\r
1930 ConfigAccess,\r
1931 Action,\r
1932 Statement->QuestionId,\r
1933 HiiValue->Type,\r
1934 TypeValue,\r
1935 &ActionRequest\r
1936 );\r
1937 if (!EFI_ERROR (Status)) {\r
bfae1330
ED
1938 //\r
1939 // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
1940 //\r
1941 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1942 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
1943 ASSERT (NewString != NULL);\r
1944\r
1945 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
1946 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
1947 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
1948 } else {\r
1949 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
1950 }\r
1951 FreePool (NewString);\r
1952 }\r
1953\r
3a4e7a3e
ED
1954 //\r
1955 // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
1956 //\r
bfae1330
ED
1957 switch (Action) {\r
1958 case EFI_BROWSER_ACTION_CHANGED:\r
3a4e7a3e
ED
1959 switch (ActionRequest) {\r
1960 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
98970c60 1961 DiscardFormIsRequired = TRUE;\r
3a4e7a3e 1962 gResetRequired = TRUE;\r
7c6c064c 1963 NeedExit = TRUE;\r
3a4e7a3e 1964 break;\r
b18e7050 1965\r
3a4e7a3e
ED
1966 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
1967 SubmitFormIsRequired = TRUE;\r
7c6c064c 1968 NeedExit = TRUE;\r
3a4e7a3e 1969 break;\r
b18e7050 1970\r
3a4e7a3e 1971 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
05b9f4cf 1972 DiscardFormIsRequired = TRUE;\r
7c6c064c 1973 NeedExit = TRUE;\r
3a4e7a3e 1974 break;\r
b18e7050 1975\r
3a4e7a3e
ED
1976 case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
1977 SubmitFormIsRequired = TRUE;\r
1978 SettingLevel = FormLevel;\r
1979 NeedExit = TRUE;\r
1980 break;\r
b18e7050 1981\r
3a4e7a3e
ED
1982 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
1983 DiscardFormIsRequired = TRUE;\r
7c6c064c 1984 SettingLevel = FormLevel;\r
3a4e7a3e
ED
1985 NeedExit = TRUE;\r
1986 break;\r
b18e7050 1987\r
3a4e7a3e
ED
1988 case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
1989 SubmitFormIsRequired = TRUE;\r
1990 SettingLevel = FormLevel;\r
1991 break;\r
b18e7050 1992\r
3a4e7a3e
ED
1993 case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
1994 DiscardFormIsRequired = TRUE;\r
1995 SettingLevel = FormLevel;\r
1996 break;\r
b18e7050 1997\r
3a4e7a3e
ED
1998 default:\r
1999 break;\r
2000 }\r
bfae1330 2001 break;\r
061d5462 2002\r
bfae1330
ED
2003 case EFI_BROWSER_ACTION_CHANGING:\r
2004 //\r
2005 // Do the question validation.\r
2006 //\r
2007 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2008 if (!EFI_ERROR (Status)) {\r
2009 //\r
2010 // According the spec, return value from call back of "changing" and \r
2011 // "retrieve" should update to the question's temp buffer.\r
2012 //\r
2013 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
061d5462 2014 }\r
bfae1330 2015 break;\r
061d5462 2016\r
bfae1330
ED
2017 case EFI_BROWSER_ACTION_RETRIEVE:\r
2018 //\r
2019 // According the spec, return value from call back of "changing" and \r
2020 // "retrieve" should update to the question's temp buffer.\r
2021 //\r
798e4d22 2022 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
bfae1330
ED
2023 break;\r
2024\r
2025 default:\r
2026 break;\r
8ca6180f 2027 }\r
c4042207 2028 } else {\r
e6cc2ab3
ED
2029 //\r
2030 // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
2031 // then the browser will use the value passed to Callback() and ignore the \r
2032 // value returned by Callback(). \r
2033 //\r
2034 if (Action == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
2035 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2036 CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
2037 } else {\r
2038 CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
2039 }\r
bfae1330
ED
2040 \r
2041 //\r
2042 // Do the question validation.\r
2043 //\r
fc2e7502
ED
2044 InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2045 if (!EFI_ERROR (InternalStatus)) {\r
bfae1330
ED
2046 SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
2047 }\r
e6cc2ab3
ED
2048 }\r
2049\r
b18e7050 2050 //\r
c4042207
ED
2051 // According the spec, return fail from call back of "changing" and \r
2052 // "retrieve", should restore the question's value.\r
b18e7050 2053 //\r
c792e5b8
ED
2054 if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) {\r
2055 if (Statement->Storage != NULL) {\r
2056 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
2057 } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2058 ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
2059 }\r
2060 }\r
2061\r
2062 if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
798e4d22 2063 GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
c4042207
ED
2064 }\r
2065\r
2066 if (Status == EFI_UNSUPPORTED) {\r
2067 //\r
2068 // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
2069 //\r
2070 Status = EFI_SUCCESS;\r
2071 }\r
b18e7050 2072 }\r
e6cc2ab3
ED
2073\r
2074 if (BackUpBuffer != NULL) {\r
2075 FreePool (BackUpBuffer);\r
2076 }\r
93551a01
ED
2077\r
2078 //\r
2079 // If Question != NULL, means just process one question\r
2080 // and if code reach here means this question has finished\r
2081 // processing, so just break.\r
2082 //\r
2083 if (Question != NULL) {\r
2084 break;\r
2085 }\r
b18e7050
ED
2086 }\r
2087\r
2088 if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2089 SubmitForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2090 }\r
2091\r
2092 if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
798e4d22 2093 DiscardForm (FormSet, Form, SettingLevel);\r
b18e7050
ED
2094 }\r
2095\r
2096 if (NeedExit) {\r
7c6c064c 2097 FindNextMenu (Selection, SettingLevel);\r
b18e7050
ED
2098 }\r
2099\r
2100 return Status;\r
2101}\r
2102\r
9776099f
ED
2103/**\r
2104 Call the retrieve type call back function for one question to get the initialize data.\r
2105 \r
2106 This function only used when in the initialize stage, because in this stage, the \r
2107 Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
2108\r
2109 @param ConfigAccess The config access protocol produced by the hii driver.\r
2110 @param Statement The Question which need to call.\r
061d5462 2111 @param FormSet The formset this question belong to.\r
9776099f
ED
2112\r
2113 @retval EFI_SUCCESS The call back function excutes successfully.\r
2114 @return Other value if the call back function failed to excute. \r
2115**/\r
2116EFI_STATUS \r
2117ProcessRetrieveForQuestion (\r
2118 IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
061d5462
ED
2119 IN FORM_BROWSER_STATEMENT *Statement,\r
2120 IN FORM_BROWSER_FORMSET *FormSet\r
9776099f
ED
2121 )\r
2122{\r
2123 EFI_STATUS Status;\r
2124 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2125 EFI_HII_VALUE *HiiValue;\r
2126 EFI_IFR_TYPE_VALUE *TypeValue;\r
061d5462 2127 CHAR16 *NewString;\r
9776099f
ED
2128\r
2129 Status = EFI_SUCCESS;\r
2130 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
70f1d5e7
ED
2131\r
2132 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
9776099f
ED
2133 return EFI_UNSUPPORTED;\r
2134 }\r
2135\r
2136 HiiValue = &Statement->HiiValue;\r
2137 TypeValue = &HiiValue->Value;\r
2138 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2139 //\r
2140 // For OrderedList, passing in the value buffer to Callback()\r
2141 //\r
2142 TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
2143 }\r
2144 \r
2145 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2146 Status = ConfigAccess->Callback (\r
2147 ConfigAccess,\r
2148 EFI_BROWSER_ACTION_RETRIEVE,\r
2149 Statement->QuestionId,\r
2150 HiiValue->Type,\r
2151 TypeValue,\r
2152 &ActionRequest\r
2153 );\r
061d5462
ED
2154 if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2155 NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
2156 ASSERT (NewString != NULL);\r
2157\r
2158 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
2159 if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
2160 CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
2161 } else {\r
2162 CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
2163 }\r
2164 FreePool (NewString);\r
2165 }\r
2166\r
9776099f
ED
2167 return Status;\r
2168}\r
2169\r
7936fb6a 2170/**\r
2171 The worker function that send the displays to the screen. On output,\r
2172 the selection made by user is returned.\r
2173\r
2174 @param Selection On input, Selection tell setup browser the information\r
2175 about the Selection, form and formset to be displayed.\r
2176 On output, Selection return the screen item that is selected\r
2177 by user.\r
2178\r
2179 @retval EFI_SUCCESS The page is displayed successfully.\r
2180 @return Other value if the page failed to be diplayed.\r
2181\r
2182**/\r
2183EFI_STATUS\r
2184SetupBrowser (\r
2185 IN OUT UI_MENU_SELECTION *Selection\r
2186 )\r
2187{\r
2188 EFI_STATUS Status;\r
2189 LIST_ENTRY *Link;\r
7936fb6a 2190 EFI_HANDLE NotifyHandle;\r
7936fb6a 2191 FORM_BROWSER_STATEMENT *Statement;\r
2192 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2193\r
5adb8db7 2194 ConfigAccess = Selection->FormSet->ConfigAccess;\r
7936fb6a 2195\r
2196 //\r
2197 // Register notify for Form package update\r
2198 //\r
2199 Status = mHiiDatabase->RegisterPackageNotify (\r
2200 mHiiDatabase,\r
8d00a0f1 2201 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 2202 NULL,\r
2203 FormUpdateNotify,\r
2204 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2205 &NotifyHandle\r
2206 );\r
2207 if (EFI_ERROR (Status)) {\r
2208 return Status;\r
2209 }\r
2210\r
d66e6c16 2211 //\r
2212 // Initialize current settings of Questions in this FormSet\r
2213 //\r
7c6c064c 2214 InitializeCurrentSetting (Selection->FormSet);\r
b9feb4bd
ED
2215\r
2216 //\r
7c6c064c 2217 // Initilize Action field.\r
b9feb4bd 2218 //\r
7c6c064c
ED
2219 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2220\r
2221 //\r
2222 // Clean the mCurFakeQestId value is formset refreshed.\r
2223 //\r
2224 mCurFakeQestId = 0;\r
48a9d5f7 2225\r
7936fb6a 2226 do {\r
54f8fc6d
ED
2227 //\r
2228 // IFR is updated, force to reparse the IFR binary\r
93551a01
ED
2229 // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and \r
2230 // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
54f8fc6d
ED
2231 //\r
2232 if (mHiiPackageListUpdated) {\r
2233 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2234 mHiiPackageListUpdated = FALSE;\r
2235 break;\r
2236 }\r
2237\r
7936fb6a 2238 //\r
2239 // Initialize Selection->Form\r
2240 //\r
2241 if (Selection->FormId == 0) {\r
2242 //\r
2243 // Zero FormId indicates display the first Form in a FormSet\r
2244 //\r
2245 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
2246\r
2247 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2248 Selection->FormId = Selection->Form->FormId;\r
2249 } else {\r
2250 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
2251 }\r
2252\r
0a1147ed
LG
2253 if (Selection->Form == NULL) {\r
2254 //\r
2255 // No Form to display\r
2256 //\r
13ad1def
LG
2257 Status = EFI_NOT_FOUND;\r
2258 goto Done;\r
0a1147ed
LG
2259 }\r
2260\r
0c66bc76
LG
2261 //\r
2262 // Check Form is suppressed.\r
2263 //\r
2264 if (Selection->Form->SuppressExpression != NULL) {\r
31585af4 2265 if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
0c66bc76
LG
2266 //\r
2267 // Form is suppressed. \r
2268 //\r
4d4deaac 2269 PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
13ad1def
LG
2270 Status = EFI_NOT_FOUND;\r
2271 goto Done;\r
0c66bc76
LG
2272 }\r
2273 }\r
5adb8db7 2274\r
5adb8db7
LG
2275 //\r
2276 // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
2277 // for each question with callback flag.\r
2278 // New form may be the first form, or the different form after another form close.\r
2279 //\r
70f1d5e7 2280 if (((Selection->Handle != mCurrentHiiHandle) ||\r
13ad1def
LG
2281 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2282 (Selection->FormId != mCurrentFormId))) {\r
6fd184d0
ED
2283 //\r
2284 // Update Retrieve flag.\r
2285 //\r
2286 mFinishRetrieveCall = FALSE;\r
2287\r
13ad1def
LG
2288 //\r
2289 // Keep current form information\r
2290 //\r
2291 mCurrentHiiHandle = Selection->Handle;\r
2292 CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
2293 mCurrentFormId = Selection->FormId;\r
2294\r
70f1d5e7 2295 if (ConfigAccess != NULL) {\r
6fd184d0 2296 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
70f1d5e7
ED
2297 if (EFI_ERROR (Status)) {\r
2298 goto Done;\r
2299 }\r
b18e7050 2300\r
70f1d5e7 2301 //\r
93551a01 2302 // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
70f1d5e7
ED
2303 //\r
2304 if (mHiiPackageListUpdated) {\r
2305 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2306 mHiiPackageListUpdated = FALSE;\r
2307 break;\r
2308 }\r
5adb8db7
LG
2309 }\r
2310 }\r
2311\r
7936fb6a 2312 //\r
2313 // Load Questions' Value for display\r
2314 //\r
eccfeab1 2315 Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
7936fb6a 2316 if (EFI_ERROR (Status)) {\r
13ad1def 2317 goto Done;\r
7936fb6a 2318 }\r
2319\r
6fd184d0
ED
2320 if (!mFinishRetrieveCall) {\r
2321 //\r
2322 // Finish call RETRIEVE callback for this form.\r
2323 //\r
2324 mFinishRetrieveCall = TRUE;\r
798e4d22 2325\r
6fd184d0
ED
2326 if (ConfigAccess != NULL) {\r
2327 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
2328 if (EFI_ERROR (Status)) {\r
2329 goto Done;\r
2330 }\r
2331\r
2332 //\r
2333 // IFR is updated during callback of open form, force to reparse the IFR binary\r
2334 //\r
2335 if (mHiiPackageListUpdated) {\r
2336 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
2337 mHiiPackageListUpdated = FALSE;\r
2338 break;\r
2339 }\r
2340 }\r
eccfeab1
LG
2341 }\r
2342\r
7936fb6a 2343 //\r
2344 // Display form\r
2345 //\r
7c6c064c 2346 Status = DisplayForm ();\r
7936fb6a 2347 if (EFI_ERROR (Status)) {\r
13ad1def 2348 goto Done;\r
7936fb6a 2349 }\r
2350\r
2351 //\r
2352 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
2353 //\r
2354 Statement = Selection->Statement;\r
2355 if (Statement != NULL) {\r
13ad1def
LG
2356 if ((ConfigAccess != NULL) && \r
2357 ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
2358 (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
798e4d22 2359 Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
7c6c064c 2360 if (Statement->Operand == EFI_IFR_REF_OP) {\r
8ca6180f
ED
2361 //\r
2362 // Process dynamic update ref opcode.\r
2363 //\r
2364 if (!EFI_ERROR (Status)) {\r
7c6c064c 2365 Status = ProcessGotoOpCode(Statement, Selection);\r
8ca6180f
ED
2366 }\r
2367 \r
3dde743f 2368 //\r
8ca6180f 2369 // Callback return error status or status return from process goto opcode.\r
3dde743f 2370 //\r
8ca6180f 2371 if (EFI_ERROR (Status)) {\r
3dde743f 2372 //\r
2373 // Cross reference will not be taken\r
2374 //\r
2375 Selection->FormId = Selection->Form->FormId;\r
2376 Selection->QuestionId = 0;\r
2377 }\r
7936fb6a 2378 }\r
b7891584 2379\r
a6c0ad81
ED
2380 //\r
2381 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2382 //\r
2383 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2384\r
ca2be854
ED
2385 if (!EFI_ERROR (Status) && \r
2386 (Statement->Operand != EFI_IFR_REF_OP) && \r
2387 ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
2388 //\r
2389 // Only question value has been changed, browser will trig CHANGED callback.\r
2390 //\r
798e4d22 2391 ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
b7891584 2392 }\r
bfae1330 2393 } else {\r
a6c0ad81 2394 //\r
bfae1330 2395 // Do the question validation.\r
a6c0ad81 2396 //\r
bfae1330
ED
2397 Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
2398 if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
2399 SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
2400 //\r
2401 // Verify whether question value has checked, update the ValueChanged flag in Question.\r
2402 //\r
2403 IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
2404 }\r
7936fb6a 2405 }\r
892eccc8 2406\r
b1239a24
ED
2407 //\r
2408 // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
2409 // trig the gResetFlag.\r
2410 //\r
2411 if ((Status == EFI_SUCCESS) && \r
2412 (Statement->Storage == NULL) && \r
2413 ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2414 gResetRequired = TRUE;\r
2415 }\r
7936fb6a 2416 }\r
7936fb6a 2417\r
7c6c064c
ED
2418 //\r
2419 // Check whether Exit flag is TRUE.\r
2420 //\r
2421 if (gExitRequired) {\r
2422 switch (gBrowserSettingScope) {\r
2423 case SystemLevel:\r
2424 Selection->Action = UI_ACTION_EXIT;\r
2425 break;\r
2426\r
2427 case FormSetLevel:\r
2428 case FormLevel:\r
2429 FindNextMenu (Selection, gBrowserSettingScope);\r
2430 break;\r
2431\r
2432 default:\r
2433 break;\r
2434 }\r
2435\r
2436 gExitRequired = FALSE;\r
2437 }\r
2438\r
5adb8db7
LG
2439 //\r
2440 // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
2441 // for each question with callback flag.\r
2442 //\r
5adb8db7
LG
2443 if ((ConfigAccess != NULL) && \r
2444 ((Selection->Action == UI_ACTION_EXIT) || \r
13ad1def
LG
2445 (Selection->Handle != mCurrentHiiHandle) ||\r
2446 (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
2447 (Selection->FormId != mCurrentFormId))) {\r
f4a2af1f 2448\r
798e4d22 2449 Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
b18e7050
ED
2450 if (EFI_ERROR (Status)) {\r
2451 goto Done;\r
f4a2af1f 2452 }\r
2453 }\r
5adb8db7 2454 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
f4a2af1f 2455\r
d66e6c16 2456Done:\r
13ad1def
LG
2457 //\r
2458 // Reset current form information to the initial setting when error happens or form exit.\r
2459 //\r
2460 if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
2461 mCurrentHiiHandle = NULL;\r
2462 CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
2463 mCurrentFormId = 0;\r
2464 }\r
2465\r
7936fb6a 2466 //\r
2467 // Unregister notify for Form package update\r
2468 //\r
13ad1def
LG
2469 mHiiDatabase->UnregisterPackageNotify (\r
2470 mHiiDatabase,\r
2471 NotifyHandle\r
2472 );\r
7936fb6a 2473 return Status;\r
2474}\r