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