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