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