]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
IntelSiliconPkg: Fixed VBT size bug, typos and updated comments
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
cb312fb1 4Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
7936fb6a 16\r
17SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
18 SETUP_DRIVER_SIGNATURE,\r
19 NULL,\r
20 {\r
21 SendForm,\r
22 BrowserCallback\r
48a9d5f7
LG
23 },\r
24 {\r
25 SetScope,\r
26 RegisterHotKey,\r
27 RegiserExitHandler,\r
28 SaveReminder\r
7c6c064c
ED
29 },\r
30 {\r
7da62bc0 31 BROWSER_EXTENSION2_VERSION_1_1,\r
7c6c064c
ED
32 SetScope,\r
33 RegisterHotKey,\r
34 RegiserExitHandler,\r
35 IsBrowserDataModified,\r
36 ExecuteAction,\r
7da62bc0
ED
37 {NULL,NULL},\r
38 {NULL,NULL},\r
39 IsResetRequired\r
7936fb6a 40 }\r
41};\r
42\r
43EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
7936fb6a 44EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
80a047f0 45EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;\r
7c6c064c 46EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;\r
7936fb6a 47\r
ce6d12cc 48UINTN gBrowserContextCount = 0;\r
49LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
48a9d5f7
LG
50LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
51LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
5a9f73bf 52LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
4d4deaac 53LIST_ENTRY gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);\r
ce6d12cc 54\r
4d4deaac 55BOOLEAN mSystemSubmit = FALSE;\r
7936fb6a 56BOOLEAN gResetRequired;\r
7c6c064c 57BOOLEAN gExitRequired;\r
f2e7732e
ED
58BOOLEAN gFlagReconnect;\r
59BOOLEAN gCallbackReconnect;\r
3c36de6c 60BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
48a9d5f7
LG
61BOOLEAN mBrowserScopeFirstSet = TRUE;\r
62EXIT_HANDLER ExitHandlerFunction = NULL;\r
6e74560f 63FORM_BROWSER_FORMSET *mSystemLevelFormSet;\r
7936fb6a 64\r
65//\r
66// Browser Global Strings\r
67//\r
7936fb6a 68CHAR16 *gEmptyString;\r
25361615 69CHAR16 *mUnknownString = L"!";\r
b9feb4bd 70\r
5a9f73bf
ED
71extern EFI_GUID mCurrentFormSetGuid;\r
72extern EFI_HII_HANDLE mCurrentHiiHandle;\r
73extern UINT16 mCurrentFormId;\r
7c6c064c
ED
74extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
75\r
76/**\r
77 Create a menu with specified formset GUID and form ID, and add it as a child\r
78 of the given parent menu.\r
79\r
80 @param HiiHandle Hii handle related to this formset.\r
81 @param FormSetGuid The Formset Guid of menu to be added.\r
82 @param FormId The Form ID of menu to be added.\r
83 @param QuestionId The question id of this menu to be added.\r
84\r
85 @return A pointer to the newly added menu or NULL if memory is insufficient.\r
86\r
87**/\r
88FORM_ENTRY_INFO *\r
89UiAddMenuList (\r
90 IN EFI_HII_HANDLE HiiHandle,\r
91 IN EFI_GUID *FormSetGuid,\r
92 IN UINT16 FormId,\r
93 IN UINT16 QuestionId\r
94 )\r
95{\r
96 FORM_ENTRY_INFO *MenuList;\r
97\r
98 MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
99 if (MenuList == NULL) {\r
100 return NULL;\r
101 }\r
102\r
103 MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
104\r
105 MenuList->HiiHandle = HiiHandle;\r
106 CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
107 MenuList->FormId = FormId;\r
108 MenuList->QuestionId = QuestionId;\r
d66e6c16 109\r
7936fb6a 110 //\r
7c6c064c 111 // If parent is not specified, it is the root Form of a Formset\r
7936fb6a 112 //\r
7c6c064c
ED
113 InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
114\r
115 return MenuList;\r
116}\r
117\r
118/**\r
119 Return the form id for the input hiihandle and formset.\r
120\r
121 @param HiiHandle HiiHandle for FormSet.\r
122 @param FormSetGuid The Formset GUID of the menu to search.\r
123\r
124 @return First form's id for this form set.\r
125\r
126**/\r
127EFI_FORM_ID\r
128GetFirstFormId (\r
129 IN EFI_HII_HANDLE HiiHandle,\r
130 IN EFI_GUID *FormSetGuid\r
131 )\r
132{\r
133 LIST_ENTRY *Link;\r
134 FORM_BROWSER_FORM *Form;\r
135\r
136 Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);\r
137 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
138\r
139 return Form->FormId;\r
140}\r
141\r
142/**\r
143 Search Menu with given FormSetGuid and FormId in all cached menu list.\r
144\r
145 @param HiiHandle HiiHandle for FormSet.\r
146 @param FormSetGuid The Formset GUID of the menu to search.\r
147 @param FormId The Form ID of menu to search.\r
148\r
149 @return A pointer to menu found or NULL if not found.\r
150\r
151**/\r
152FORM_ENTRY_INFO *\r
153UiFindMenuList (\r
154 IN EFI_HII_HANDLE HiiHandle, \r
155 IN EFI_GUID *FormSetGuid,\r
156 IN UINT16 FormId\r
157 )\r
158{\r
159 LIST_ENTRY *Link;\r
160 FORM_ENTRY_INFO *MenuList;\r
161 FORM_ENTRY_INFO *RetMenu;\r
162 EFI_FORM_ID FirstFormId;\r
163\r
164 RetMenu = NULL;\r
165\r
166 Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
167 while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {\r
168 MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
169 Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);\r
170 \r
171 //\r
172 // If already find the menu, free the menus behind it.\r
173 //\r
174 if (RetMenu != NULL) {\r
175 RemoveEntryList (&MenuList->Link);\r
176 FreePool (MenuList);\r
177 continue;\r
178 }\r
179\r
180 //\r
181 // Find the same FromSet.\r
182 //\r
183 if (MenuList->HiiHandle == HiiHandle) {\r
184 if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {\r
185 //\r
186 // FormSetGuid is not specified.\r
187 //\r
188 RetMenu = MenuList;\r
189 } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {\r
190 if (MenuList->FormId == FormId) {\r
191 RetMenu = MenuList;\r
192 } else if (FormId == 0 || MenuList->FormId == 0 ) {\r
193 FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);\r
194 if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) {\r
195 RetMenu = MenuList;\r
196 }\r
197 }\r
7936fb6a 198 }\r
7c6c064c
ED
199 }\r
200 }\r
201\r
202 return RetMenu;\r
203}\r
204\r
205/**\r
206 Find parent menu for current menu.\r
207\r
208 @param CurrentMenu Current Menu\r
93551a01
ED
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.\r
210 In form level, just find the parent menu; \r
211 In formset level, find the parent menu which has different\r
212 formset guid value.\r
7c6c064c
ED
213\r
214 @retval The parent menu for current menu.\r
215**/\r
216FORM_ENTRY_INFO *\r
217UiFindParentMenu (\r
93551a01
ED
218 IN FORM_ENTRY_INFO *CurrentMenu,\r
219 IN BROWSER_SETTING_SCOPE SettingLevel\r
7c6c064c
ED
220 )\r
221{\r
222 FORM_ENTRY_INFO *ParentMenu;\r
93551a01
ED
223 LIST_ENTRY *Link;\r
224\r
225 ASSERT (SettingLevel == FormLevel || SettingLevel == FormSetLevel);\r
7c6c064c 226\r
93551a01
ED
227 if (CurrentMenu == NULL) {\r
228 return NULL;\r
229 }\r
230 \r
7c6c064c 231 ParentMenu = NULL;\r
93551a01
ED
232 Link = &CurrentMenu->Link;\r
233\r
234 while (Link->BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
235 ParentMenu = FORM_ENTRY_INFO_FROM_LINK (Link->BackLink);\r
236\r
237 if (SettingLevel == FormLevel) {\r
238 //\r
239 // For FormLevel, just find the parent menu, return.\r
240 //\r
241 break;\r
242 }\r
243\r
244 if (!CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
245 //\r
246 // For SystemLevel, must find the menu which has different formset.\r
247 //\r
248 break;\r
249 }\r
250\r
251 Link = Link->BackLink;\r
252 }\r
253\r
254 //\r
255 // Not find the parent menu, just return NULL.\r
256 //\r
257 if (Link->BackLink == &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
258 return NULL;\r
7c6c064c
ED
259 }\r
260\r
261 return ParentMenu;\r
262}\r
263\r
264/**\r
265 Free Menu list linked list.\r
266\r
267 @param MenuListHead One Menu list point in the menu list.\r
268\r
269**/\r
270VOID\r
271UiFreeMenuList (\r
272 LIST_ENTRY *MenuListHead\r
273 )\r
274{\r
275 FORM_ENTRY_INFO *MenuList;\r
276\r
277 while (!IsListEmpty (MenuListHead)) {\r
278 MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);\r
279 RemoveEntryList (&MenuList->Link);\r
280\r
281 FreePool (MenuList);\r
282 }\r
283}\r
284\r
4d4deaac
ED
285/**\r
286 Copy current Menu list to the new menu list.\r
287 \r
288 @param NewMenuListHead New create Menu list.\r
289 @param CurrentMenuListHead Current Menu list.\r
290\r
291**/\r
292VOID\r
293UiCopyMenuList (\r
294 OUT LIST_ENTRY *NewMenuListHead,\r
295 IN LIST_ENTRY *CurrentMenuListHead\r
296 )\r
297{\r
298 LIST_ENTRY *Link;\r
299 FORM_ENTRY_INFO *MenuList;\r
300 FORM_ENTRY_INFO *NewMenuEntry;\r
301\r
302 //\r
303 // If new menu list not empty, free it first.\r
304 //\r
305 UiFreeMenuList (NewMenuListHead);\r
306\r
307 Link = GetFirstNode (CurrentMenuListHead);\r
308 while (!IsNull (CurrentMenuListHead, Link)) {\r
309 MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
310 Link = GetNextNode (CurrentMenuListHead, Link);\r
311\r
312 NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
313 ASSERT (NewMenuEntry != NULL);\r
314 NewMenuEntry->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
315 NewMenuEntry->HiiHandle = MenuList->HiiHandle;\r
316 CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));\r
317 NewMenuEntry->FormId = MenuList->FormId;\r
318 NewMenuEntry->QuestionId = MenuList->QuestionId;\r
319\r
320 InsertTailList (NewMenuListHead, &NewMenuEntry->Link);\r
321 }\r
322}\r
323\r
7c6c064c
ED
324/**\r
325 Load all hii formset to the browser.\r
326\r
327**/\r
328VOID\r
329LoadAllHiiFormset (\r
330 VOID\r
331 )\r
332{\r
333 FORM_BROWSER_FORMSET *LocalFormSet;\r
334 EFI_HII_HANDLE *HiiHandles;\r
335 UINTN Index;\r
336 EFI_GUID ZeroGuid;\r
337 EFI_STATUS Status;\r
6e74560f
ED
338 FORM_BROWSER_FORMSET *OldFormset;\r
339\r
340 OldFormset = mSystemLevelFormSet;\r
7c6c064c 341\r
7936fb6a 342 //\r
7c6c064c 343 // Get all the Hii handles\r
7936fb6a 344 //\r
7c6c064c
ED
345 HiiHandles = HiiGetHiiHandles (NULL);\r
346 ASSERT (HiiHandles != NULL);\r
347\r
7936fb6a 348 //\r
7c6c064c 349 // Search for formset of each class type\r
7936fb6a 350 //\r
7c6c064c
ED
351 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
352 //\r
353 // Check HiiHandles[Index] does exist in global maintain list.\r
354 //\r
355 if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
356 continue;\r
357 }\r
358\r
359 //\r
360 // Initilize FormSet Setting\r
361 //\r
362 LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
363 ASSERT (LocalFormSet != NULL);\r
6e74560f
ED
364 mSystemLevelFormSet = LocalFormSet;\r
365\r
7c6c064c
ED
366 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
367 Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
368 if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
369 DestroyFormSet (LocalFormSet);\r
370 continue;\r
371 }\r
372 InitializeCurrentSetting (LocalFormSet);\r
373\r
374 //\r
375 // Initilize Questions' Value\r
376 //\r
377 Status = LoadFormSetConfig (NULL, LocalFormSet);\r
378 if (EFI_ERROR (Status)) {\r
379 DestroyFormSet (LocalFormSet);\r
380 continue;\r
381 }\r
382 }\r
383\r
7936fb6a 384 //\r
7c6c064c 385 // Free resources, and restore gOldFormSet and gClassOfVfr\r
7936fb6a 386 //\r
7c6c064c 387 FreePool (HiiHandles);\r
6e74560f
ED
388\r
389 mSystemLevelFormSet = OldFormset;\r
7c6c064c 390}\r
7936fb6a 391\r
bfae1330
ED
392/**\r
393 Pop up the error info.\r
394\r
395 @param BrowserStatus The input browser status.\r
4d4deaac 396 @param HiiHandle The Hiihandle for this opcode.\r
bfae1330
ED
397 @param OpCode The opcode use to get the erro info and timeout value.\r
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.\r
399\r
400**/\r
4d4deaac 401UINT32\r
bfae1330
ED
402PopupErrorMessage (\r
403 IN UINT32 BrowserStatus,\r
4d4deaac 404 IN EFI_HII_HANDLE HiiHandle,\r
bfae1330
ED
405 IN EFI_IFR_OP_HEADER *OpCode, OPTIONAL\r
406 IN CHAR16 *ErrorString\r
407 )\r
408{\r
409 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
4d4deaac 410 USER_INPUT UserInputData;\r
bfae1330
ED
411\r
412 Statement = NULL;\r
413\r
414 if (OpCode != NULL) {\r
415 Statement = AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT));\r
416 ASSERT (Statement != NULL);\r
417 Statement->OpCode = OpCode;\r
418 gDisplayFormData.HighLightedStatement = Statement;\r
419 }\r
420\r
421 //\r
422 // Used to compatible with old display engine.\r
423 // New display engine not use this field.\r
424 //\r
425 gDisplayFormData.ErrorString = ErrorString;\r
426 gDisplayFormData.BrowserStatus = BrowserStatus;\r
4d4deaac
ED
427\r
428 if (HiiHandle != NULL) {\r
429 gDisplayFormData.HiiHandle = HiiHandle;\r
430 }\r
431\r
432 mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);\r
bfae1330
ED
433\r
434 gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;\r
435 gDisplayFormData.ErrorString = NULL;\r
436\r
437 if (OpCode != NULL) {\r
438 FreePool (Statement);\r
439 }\r
4d4deaac
ED
440\r
441 return UserInputData.Action;\r
bfae1330
ED
442}\r
443\r
7936fb6a 444/**\r
445 This is the routine which an external caller uses to direct the browser\r
446 where to obtain it's information.\r
447\r
448\r
449 @param This The Form Browser protocol instanse.\r
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
451 display a list of the formsets for the handles specified.\r
452 @param HandleCount The number of Handles specified in Handle.\r
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
454 field in the EFI_IFR_FORM_SET op-code for the specified\r
455 forms-based package. If FormSetGuid is NULL, then this\r
456 function will display the first found forms package.\r
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
458 displayable page. If this field has a value of 0x0000, then\r
459 the forms browser will render the specified forms in their encoded order.\r
d66e6c16 460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
7936fb6a 461 characters.\r
f02d0c0f 462 @param ActionRequest Points to the action recommended by the form.\r
7936fb6a 463\r
464 @retval EFI_SUCCESS The function completed successfully.\r
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
466 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
467\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471SendForm (\r
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
473 IN EFI_HII_HANDLE *Handles,\r
474 IN UINTN HandleCount,\r
475 IN EFI_GUID *FormSetGuid, OPTIONAL\r
476 IN UINT16 FormId, OPTIONAL\r
477 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
478 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
479 )\r
480{\r
519f076a 481 EFI_STATUS Status;\r
482 UI_MENU_SELECTION *Selection;\r
483 UINTN Index;\r
484 FORM_BROWSER_FORMSET *FormSet;\r
7c6c064c 485 FORM_ENTRY_INFO *MenuList;\r
f2e7732e 486 BOOLEAN RetVal;\r
48a9d5f7
LG
487\r
488 //\r
7c6c064c 489 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
48a9d5f7 490 //\r
7c6c064c 491 if (mFormDisplay == NULL) {\r
0b5c288c 492 DEBUG ((DEBUG_ERROR, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));\r
7c6c064c 493 return EFI_UNSUPPORTED;\r
48a9d5f7 494 }\r
c40bd442 495\r
ce6d12cc 496 //\r
497 // Save globals used by SendForm()\r
498 //\r
499 SaveBrowserContext ();\r
500\r
f2e7732e 501 gFlagReconnect = FALSE;\r
48a9d5f7 502 gResetRequired = FALSE;\r
7c6c064c 503 gExitRequired = FALSE;\r
f2e7732e 504 gCallbackReconnect = FALSE;\r
7c6c064c
ED
505 Status = EFI_SUCCESS;\r
506 gEmptyString = L"";\r
507 gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;\r
519f076a 508\r
7936fb6a 509 for (Index = 0; Index < HandleCount; Index++) {\r
510 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
511 ASSERT (Selection != NULL);\r
512\r
513 Selection->Handle = Handles[Index];\r
514 if (FormSetGuid != NULL) {\r
515 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
516 Selection->FormId = FormId;\r
48a9d5f7
LG
517 } else {\r
518 CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
7936fb6a 519 }\r
520\r
521 do {\r
522 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
523 ASSERT (FormSet != NULL);\r
524\r
93551a01
ED
525 //\r
526 // Validate the HiiHandle\r
527 // if validate failed, find the first validate parent HiiHandle.\r
528 //\r
529 if (!ValidateHiiHandle(Selection->Handle)) {\r
530 FindNextMenu (Selection, FormSetLevel);\r
531 }\r
532\r
7936fb6a 533 //\r
534 // Initialize internal data structures of FormSet\r
535 //\r
7c6c064c 536 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
e8e36190 537 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
7936fb6a 538 DestroyFormSet (FormSet);\r
539 break;\r
540 }\r
541 Selection->FormSet = FormSet;\r
6e74560f 542 mSystemLevelFormSet = FormSet;\r
7936fb6a 543\r
7936fb6a 544 //\r
545 // Display this formset\r
546 //\r
547 gCurrentSelection = Selection;\r
548\r
549 Status = SetupBrowser (Selection);\r
550\r
551 gCurrentSelection = NULL;\r
6e74560f 552 mSystemLevelFormSet = NULL;\r
7936fb6a 553\r
f2e7732e
ED
554 if (gFlagReconnect || gCallbackReconnect) {\r
555 RetVal = ReconnectController (FormSet->DriverHandle);\r
556 if (!RetVal) {\r
557 PopupErrorMessage(BROWSER_RECONNECT_FAIL, NULL, NULL, NULL);\r
558 }\r
559 gFlagReconnect = FALSE;\r
560 gCallbackReconnect = FALSE;\r
561 }\r
562\r
25361615
ED
563 //\r
564 // If no data is changed, don't need to save current FormSet into the maintain list.\r
565 //\r
27c304f4 566 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
7c6c064c
ED
567 CleanBrowserStorage(FormSet);\r
568 RemoveEntryList (&FormSet->Link);\r
569 DestroyFormSet (FormSet);\r
25361615 570 }\r
7c6c064c
ED
571\r
572 if (EFI_ERROR (Status)) {\r
573 break;\r
574 }\r
575 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
b9feb4bd 576\r
25361615 577 FreePool (Selection);\r
b9feb4bd
ED
578 }\r
579\r
7936fb6a 580 if (ActionRequest != NULL) {\r
581 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
582 if (gResetRequired) {\r
583 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
584 }\r
585 }\r
586\r
7c6c064c 587 mFormDisplay->ExitDisplay();\r
7936fb6a 588\r
7c6c064c
ED
589 //\r
590 // Clear the menu history data.\r
591 //\r
592 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
593 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
594 RemoveEntryList (&MenuList->Link);\r
595 FreePool (MenuList);\r
596 }\r
7936fb6a 597\r
ce6d12cc 598 //\r
599 // Restore globals used by SendForm()\r
600 //\r
601 RestoreBrowserContext ();\r
602\r
7936fb6a 603 return Status;\r
604}\r
605\r
7c6c064c
ED
606/**\r
607 Get or set data to the storage.\r
608\r
609 @param ResultsDataSize The size of the buffer associatedwith ResultsData.\r
610 @param ResultsData A string returned from an IFR browser or\r
611 equivalent. The results string will have no\r
612 routing information in them.\r
613 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
614 (if RetrieveData = TRUE) data from the uncommitted\r
615 browser state information or set (if RetrieveData\r
616 = FALSE) data in the uncommitted browser state\r
617 information.\r
618 @param Storage The pointer to the storage.\r
619\r
620 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
621 distribution.\r
622\r
623**/\r
624EFI_STATUS \r
625ProcessStorage (\r
626 IN OUT UINTN *ResultsDataSize,\r
627 IN OUT EFI_STRING *ResultsData,\r
628 IN BOOLEAN RetrieveData,\r
629 IN BROWSER_STORAGE *Storage\r
630 )\r
631{\r
632 CHAR16 *ConfigResp;\r
633 EFI_STATUS Status;\r
634 CHAR16 *StrPtr;\r
635 UINTN BufferSize;\r
636 UINTN TmpSize;\r
5ad66ec6 637 UINTN MaxLen;\r
a35ecb75 638 FORMSET_STORAGE *BrowserStorage;\r
7c6c064c
ED
639\r
640 if (RetrieveData) {\r
641 //\r
642 // Generate <ConfigResp>\r
643 //\r
644 Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);\r
645 if (EFI_ERROR (Status)) {\r
646 return Status;\r
647 }\r
648\r
649 //\r
650 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.\r
651 // Also need to consider add "\0" at first time.\r
652 //\r
a35ecb75
ED
653 StrPtr = StrStr (ConfigResp, L"PATH");\r
654 ASSERT (StrPtr != NULL);\r
655 StrPtr = StrStr (StrPtr, L"&");\r
656 StrPtr += 1;\r
7c6c064c
ED
657 BufferSize = StrSize (StrPtr);\r
658\r
7c6c064c
ED
659 //\r
660 // Copy the data if the input buffer is bigger enough.\r
661 //\r
662 if (*ResultsDataSize >= BufferSize) {\r
5ad66ec6 663 StrCpyS (*ResultsData, *ResultsDataSize / sizeof (CHAR16), StrPtr);\r
7c6c064c
ED
664 }\r
665\r
666 *ResultsDataSize = BufferSize;\r
667 FreePool (ConfigResp);\r
668 } else {\r
669 //\r
670 // Prepare <ConfigResp>\r
671 //\r
a35ecb75
ED
672 BrowserStorage = GetFstStgFromBrsStg (Storage);\r
673 ASSERT (BrowserStorage != NULL);\r
7c6c064c 674 TmpSize = StrLen (*ResultsData);\r
a35ecb75 675 BufferSize = (TmpSize + StrLen (BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
5ad66ec6 676 MaxLen = BufferSize / sizeof (CHAR16);\r
7c6c064c
ED
677 ConfigResp = AllocateZeroPool (BufferSize);\r
678 ASSERT (ConfigResp != NULL);\r
679\r
5ad66ec6
DB
680 StrCpyS (ConfigResp, MaxLen, BrowserStorage->ConfigHdr);\r
681 StrCatS (ConfigResp, MaxLen, L"&");\r
682 StrCatS (ConfigResp, MaxLen, *ResultsData);\r
7c6c064c
ED
683\r
684 //\r
685 // Update Browser uncommited data\r
686 //\r
687 Status = ConfigRespToStorage (Storage, ConfigResp);\r
688 FreePool (ConfigResp);\r
689 if (EFI_ERROR (Status)) {\r
690 return Status;\r
691 }\r
692 }\r
693\r
694 return EFI_SUCCESS;\r
695}\r
7936fb6a 696\r
697/**\r
7c6c064c
ED
698 This routine called this service in the browser to retrieve or set certain uncommitted \r
699 state information that resides in the open formsets. \r
7936fb6a 700\r
701 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
702 instance.\r
703 @param ResultsDataSize A pointer to the size of the buffer associated\r
704 with ResultsData.\r
705 @param ResultsData A string returned from an IFR browser or\r
706 equivalent. The results string will have no\r
707 routing information in them.\r
708 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
709 (if RetrieveData = TRUE) data from the uncommitted\r
710 browser state information or set (if RetrieveData\r
711 = FALSE) data in the uncommitted browser state\r
712 information.\r
713 @param VariableGuid An optional field to indicate the target variable\r
714 GUID name to use.\r
715 @param VariableName An optional field to indicate the target\r
716 human-readable variable name.\r
717\r
718 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
719 distribution.\r
720 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
721 contain the results data.\r
722\r
723**/\r
724EFI_STATUS\r
725EFIAPI\r
726BrowserCallback (\r
727 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
728 IN OUT UINTN *ResultsDataSize,\r
729 IN OUT EFI_STRING ResultsData,\r
730 IN BOOLEAN RetrieveData,\r
731 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
732 IN CONST CHAR16 *VariableName OPTIONAL\r
733 )\r
734{\r
735 EFI_STATUS Status;\r
736 LIST_ENTRY *Link;\r
7c6c064c
ED
737 BROWSER_STORAGE *Storage;\r
738 FORMSET_STORAGE *FormsetStorage;\r
7c6c064c 739 UINTN TotalSize;\r
7936fb6a 740 BOOLEAN Found;\r
7936fb6a 741\r
742 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
743 return EFI_INVALID_PARAMETER;\r
744 }\r
745\r
7c6c064c
ED
746 TotalSize = *ResultsDataSize;\r
747 Storage = NULL;\r
748 Found = FALSE;\r
749 Status = EFI_SUCCESS;\r
7936fb6a 750\r
7936fb6a 751 if (VariableGuid != NULL) {\r
752 //\r
7c6c064c 753 // Try to find target storage in the current formset.\r
7936fb6a 754 //\r
7c6c064c
ED
755 Link = GetFirstNode (&gBrowserStorageList);\r
756 while (!IsNull (&gBrowserStorageList, Link)) {\r
757 Storage = BROWSER_STORAGE_FROM_LINK (Link);\r
758 Link = GetNextNode (&gBrowserStorageList, Link);\r
759 //\r
760 // Check the current storage.\r
761 //\r
762 if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
763 continue;\r
764 }\r
7936fb6a 765\r
7c6c064c
ED
766 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||\r
767 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
768 //\r
769 // Buffer storage require both GUID and Name\r
770 //\r
771 if (VariableName == NULL) {\r
772 return EFI_NOT_FOUND;\r
773 }\r
7936fb6a 774\r
7c6c064c
ED
775 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
776 continue;\r
7936fb6a 777 }\r
7936fb6a 778 }\r
7c6c064c 779\r
fae73624
ED
780 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE ||\r
781 Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
782 if (mSystemLevelFormSet == NULL || mSystemLevelFormSet->HiiHandle == NULL) {\r
783 return EFI_NOT_FOUND;\r
784 }\r
785\r
786 if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) {\r
787 continue;\r
788 }\r
789 }\r
790\r
7c6c064c
ED
791 Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
792 if (EFI_ERROR (Status)) {\r
793 return Status;\r
794 }\r
795\r
9d34cac8
ED
796 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
797 ConfigRequestAdjust (Storage, ResultsData, TRUE);\r
798 }\r
799\r
7c6c064c
ED
800 //\r
801 // Different formsets may have same varstore, so here just set the flag\r
802 // not exit the circle.\r
803 // \r
804 Found = TRUE;\r
805 break;\r
7936fb6a 806 }\r
807\r
808 if (!Found) {\r
809 return EFI_NOT_FOUND;\r
810 }\r
811 } else {\r
812 //\r
813 // GUID/Name is not specified, take the first storage in FormSet\r
814 //\r
6e74560f 815 if (mSystemLevelFormSet == NULL) {\r
7c6c064c 816 return EFI_NOT_READY;\r
b9feb4bd
ED
817 }\r
818\r
25361615
ED
819 //\r
820 // Generate <ConfigResp>\r
821 //\r
6e74560f
ED
822 Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead);\r
823 if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) {\r
7c6c064c
ED
824 return EFI_UNSUPPORTED;\r
825 }\r
826\r
827 FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
828 \r
829 Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
7936fb6a 830 if (EFI_ERROR (Status)) {\r
831 return Status;\r
832 }\r
7c6c064c 833 }\r
7936fb6a 834\r
7c6c064c
ED
835 if (RetrieveData) {\r
836 Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
837 *ResultsDataSize = TotalSize;\r
838 }\r
839 \r
840 return Status;\r
7936fb6a 841\r
7c6c064c 842}\r
7936fb6a 843\r
7936fb6a 844\r
7c6c064c
ED
845/**\r
846 Callback function for SimpleTextInEx protocol install events\r
7936fb6a 847\r
7c6c064c
ED
848 @param Event the event that is signaled.\r
849 @param Context not used here.\r
7936fb6a 850\r
7c6c064c
ED
851**/\r
852VOID\r
853EFIAPI\r
854FormDisplayCallback (\r
855 IN EFI_EVENT Event,\r
856 IN VOID *Context\r
857 )\r
858{\r
7c6c064c
ED
859 if (mFormDisplay != NULL) {\r
860 return;\r
7936fb6a 861 }\r
862\r
831537d6 863 gBS->LocateProtocol (\r
7c6c064c
ED
864 &gEdkiiFormDisplayEngineProtocolGuid,\r
865 NULL,\r
866 (VOID **) &mFormDisplay\r
867 );\r
7936fb6a 868}\r
869\r
7936fb6a 870/**\r
871 Initialize Setup Browser driver.\r
872\r
873 @param ImageHandle The image handle.\r
874 @param SystemTable The system table.\r
875\r
876 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
877 @return Other value if failed to initialize the Setup Browser module.\r
878\r
879**/\r
880EFI_STATUS\r
881EFIAPI\r
882InitializeSetup (\r
883 IN EFI_HANDLE ImageHandle,\r
884 IN EFI_SYSTEM_TABLE *SystemTable\r
885 )\r
886{\r
887 EFI_STATUS Status;\r
7c6c064c 888 VOID *Registration;\r
7936fb6a 889\r
890 //\r
891 // Locate required Hii relative protocols\r
892 //\r
893 Status = gBS->LocateProtocol (\r
894 &gEfiHiiDatabaseProtocolGuid,\r
895 NULL,\r
896 (VOID **) &mHiiDatabase\r
897 );\r
898 ASSERT_EFI_ERROR (Status);\r
899\r
7936fb6a 900 Status = gBS->LocateProtocol (\r
901 &gEfiHiiConfigRoutingProtocolGuid,\r
902 NULL,\r
903 (VOID **) &mHiiConfigRouting\r
904 );\r
905 ASSERT_EFI_ERROR (Status);\r
906\r
80a047f0
ED
907 Status = gBS->LocateProtocol (\r
908 &gEfiDevicePathFromTextProtocolGuid,\r
909 NULL,\r
910 (VOID **) &mPathFromText\r
911 );\r
912\r
7936fb6a 913 //\r
914 // Install FormBrowser2 protocol\r
915 //\r
916 mPrivateData.Handle = NULL;\r
917 Status = gBS->InstallProtocolInterface (\r
918 &mPrivateData.Handle,\r
919 &gEfiFormBrowser2ProtocolGuid,\r
920 EFI_NATIVE_INTERFACE,\r
921 &mPrivateData.FormBrowser2\r
922 );\r
923 ASSERT_EFI_ERROR (Status);\r
924\r
48a9d5f7 925 //\r
7c6c064c 926 // Install FormBrowserEx2 protocol\r
48a9d5f7 927 //\r
184f3a02
ED
928 InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
929 InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
48a9d5f7 930 mPrivateData.Handle = NULL;\r
7c6c064c
ED
931 Status = gBS->InstallProtocolInterface (\r
932 &mPrivateData.Handle,\r
933 &gEdkiiFormBrowserEx2ProtocolGuid,\r
934 EFI_NATIVE_INTERFACE,\r
935 &mPrivateData.FormBrowserEx2\r
936 );\r
937 ASSERT_EFI_ERROR (Status);\r
938 \r
48a9d5f7
LG
939 Status = gBS->InstallProtocolInterface (\r
940 &mPrivateData.Handle,\r
941 &gEfiFormBrowserExProtocolGuid,\r
942 EFI_NATIVE_INTERFACE,\r
943 &mPrivateData.FormBrowserEx\r
944 );\r
7c6c064c
ED
945 ASSERT_EFI_ERROR (Status);\r
946\r
947 InitializeDisplayFormData ();\r
948\r
949 Status = gBS->LocateProtocol (\r
950 &gEdkiiFormDisplayEngineProtocolGuid,\r
951 NULL,\r
952 (VOID **) &mFormDisplay\r
953 );\r
48a9d5f7 954\r
7c6c064c
ED
955 if (EFI_ERROR (Status)) {\r
956 EfiCreateProtocolNotifyEvent (\r
957 &gEdkiiFormDisplayEngineProtocolGuid,\r
958 TPL_CALLBACK,\r
959 FormDisplayCallback,\r
960 NULL,\r
961 &Registration\r
962 );\r
963 }\r
964 \r
965 return EFI_SUCCESS;\r
7936fb6a 966}\r
967\r
968\r
969/**\r
970 Create a new string in HII Package List.\r
971\r
972 @param String The String to be added\r
973 @param HiiHandle The package list in the HII database to insert the\r
974 specified string.\r
975\r
976 @return The output string.\r
977\r
978**/\r
979EFI_STRING_ID\r
980NewString (\r
981 IN CHAR16 *String,\r
982 IN EFI_HII_HANDLE HiiHandle\r
983 )\r
984{\r
985 EFI_STRING_ID StringId;\r
7936fb6a 986\r
cb7d01c0 987 StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
988 ASSERT (StringId != 0);\r
7936fb6a 989\r
990 return StringId;\r
991}\r
992\r
993\r
994/**\r
995 Delete a string from HII Package List.\r
996\r
997 @param StringId Id of the string in HII database.\r
998 @param HiiHandle The HII package list handle.\r
999\r
1000 @retval EFI_SUCCESS The string was deleted successfully.\r
1001\r
1002**/\r
1003EFI_STATUS\r
1004DeleteString (\r
1005 IN EFI_STRING_ID StringId,\r
1006 IN EFI_HII_HANDLE HiiHandle\r
1007 )\r
1008{\r
1009 CHAR16 NullChar;\r
1010\r
1011 NullChar = CHAR_NULL;\r
cb7d01c0 1012 HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
1013 return EFI_SUCCESS;\r
7936fb6a 1014}\r
1015\r
1016\r
1017/**\r
1018 Get the string based on the StringId and HII Package List Handle.\r
1019\r
1020 @param Token The String's ID.\r
1021 @param HiiHandle The package list in the HII database to search for\r
1022 the specified string.\r
1023\r
1024 @return The output string.\r
1025\r
1026**/\r
1027CHAR16 *\r
1028GetToken (\r
1029 IN EFI_STRING_ID Token,\r
1030 IN EFI_HII_HANDLE HiiHandle\r
1031 )\r
1032{\r
cb7d01c0 1033 EFI_STRING String;\r
7936fb6a 1034\r
2573712e
LG
1035 if (HiiHandle == NULL) {\r
1036 return NULL;\r
1037 }\r
1038\r
cb7d01c0 1039 String = HiiGetString (HiiHandle, Token, NULL);\r
0e8e994d 1040 if (String == NULL) {\r
d6bee311 1041 String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
0e8e994d 1042 ASSERT (String != NULL);\r
1043 }\r
cb7d01c0 1044 return (CHAR16 *) String;\r
7936fb6a 1045}\r
1046\r
1047\r
1048/**\r
1049 Allocate new memory and then copy the Unicode string Source to Destination.\r
1050\r
1051 @param Dest Location to copy string\r
1052 @param Src String to copy\r
1053\r
1054**/\r
1055VOID\r
1056NewStringCpy (\r
1057 IN OUT CHAR16 **Dest,\r
1058 IN CHAR16 *Src\r
1059 )\r
1060{\r
676df92c 1061 if (*Dest != NULL) {\r
1062 FreePool (*Dest);\r
1063 }\r
7936fb6a 1064 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
1065 ASSERT (*Dest != NULL);\r
1066}\r
1067\r
1068\r
1069/**\r
1070 Allocate new memory and concatinate Source on the end of Destination.\r
1071\r
1072 @param Dest String to added to the end of.\r
1073 @param Src String to concatinate.\r
1074\r
1075**/\r
1076VOID\r
1077NewStringCat (\r
1078 IN OUT CHAR16 **Dest,\r
1079 IN CHAR16 *Src\r
1080 )\r
1081{\r
1082 CHAR16 *NewString;\r
5ad66ec6 1083 UINTN MaxLen;\r
7936fb6a 1084\r
1085 if (*Dest == NULL) {\r
1086 NewStringCpy (Dest, Src);\r
1087 return;\r
1088 }\r
1089\r
5ad66ec6
DB
1090 MaxLen = ( StrSize (*Dest) + StrSize (Src) - 1) / sizeof (CHAR16);\r
1091 NewString = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
25361615
ED
1092 ASSERT (NewString != NULL);\r
1093\r
5ad66ec6
DB
1094 StrCpyS (NewString, MaxLen, *Dest);\r
1095 StrCatS (NewString, MaxLen, Src);\r
25361615
ED
1096\r
1097 FreePool (*Dest);\r
1098 *Dest = NewString;\r
1099}\r
1100\r
7936fb6a 1101/**\r
1102 Get Value for given Name from a NameValue Storage.\r
1103\r
1104 @param Storage The NameValue Storage.\r
1105 @param Name The Name.\r
1106 @param Value The retured Value.\r
816a7110 1107 @param GetValueFrom Where to get source value, from EditValue or Value.\r
7936fb6a 1108\r
1109 @retval EFI_SUCCESS Value found for given Name.\r
1110 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
1111\r
1112**/\r
1113EFI_STATUS\r
1114GetValueByName (\r
94f3aae7 1115 IN BROWSER_STORAGE *Storage,\r
816a7110
ED
1116 IN CHAR16 *Name,\r
1117 IN OUT CHAR16 **Value,\r
1118 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
7936fb6a 1119 )\r
1120{\r
1121 LIST_ENTRY *Link;\r
1122 NAME_VALUE_NODE *Node;\r
1123\r
816a7110
ED
1124 if (GetValueFrom != GetSetValueWithEditBuffer && GetValueFrom != GetSetValueWithBuffer) {\r
1125 return EFI_INVALID_PARAMETER;\r
1126 }\r
1127\r
7936fb6a 1128 *Value = NULL;\r
1129\r
1130 Link = GetFirstNode (&Storage->NameValueListHead);\r
1131 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1132 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1133\r
1134 if (StrCmp (Name, Node->Name) == 0) {\r
816a7110
ED
1135 if (GetValueFrom == GetSetValueWithEditBuffer) {\r
1136 NewStringCpy (Value, Node->EditValue);\r
1137 } else {\r
1138 NewStringCpy (Value, Node->Value);\r
1139 }\r
7936fb6a 1140 return EFI_SUCCESS;\r
1141 }\r
1142\r
1143 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1144 }\r
1145\r
1146 return EFI_NOT_FOUND;\r
1147}\r
1148\r
1149\r
1150/**\r
1151 Set Value of given Name in a NameValue Storage.\r
1152\r
1153 @param Storage The NameValue Storage.\r
1154 @param Name The Name.\r
1155 @param Value The Value to set.\r
816a7110 1156 @param SetValueTo Whether update editValue or Value.\r
7c6c064c 1157 @param ReturnNode The node use the input name.\r
7936fb6a 1158\r
1159 @retval EFI_SUCCESS Value found for given Name.\r
1160 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
1161\r
1162**/\r
1163EFI_STATUS\r
1164SetValueByName (\r
7c6c064c
ED
1165 IN BROWSER_STORAGE *Storage,\r
1166 IN CHAR16 *Name,\r
1167 IN CHAR16 *Value,\r
1168 IN GET_SET_QUESTION_VALUE_WITH SetValueTo,\r
1169 OUT NAME_VALUE_NODE **ReturnNode\r
7936fb6a 1170 )\r
1171{\r
1172 LIST_ENTRY *Link;\r
1173 NAME_VALUE_NODE *Node;\r
b18e7050 1174 CHAR16 *Buffer;\r
7936fb6a 1175\r
816a7110
ED
1176 if (SetValueTo != GetSetValueWithEditBuffer && SetValueTo != GetSetValueWithBuffer) {\r
1177 return EFI_INVALID_PARAMETER;\r
1178 }\r
1179\r
7936fb6a 1180 Link = GetFirstNode (&Storage->NameValueListHead);\r
1181 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1182 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1183\r
1184 if (StrCmp (Name, Node->Name) == 0) {\r
816a7110 1185 if (SetValueTo == GetSetValueWithEditBuffer) {\r
b18e7050
ED
1186 Buffer = Node->EditValue;\r
1187 } else {\r
1188 Buffer = Node->Value;\r
1189 }\r
1190 if (Buffer != NULL) {\r
1191 FreePool (Buffer);\r
1192 }\r
1193 Buffer = AllocateCopyPool (StrSize (Value), Value);\r
1194 ASSERT (Buffer != NULL);\r
816a7110 1195 if (SetValueTo == GetSetValueWithEditBuffer) {\r
b18e7050
ED
1196 Node->EditValue = Buffer;\r
1197 } else {\r
1198 Node->Value = Buffer;\r
676df92c 1199 }\r
7c6c064c
ED
1200\r
1201 if (ReturnNode != NULL) {\r
1202 *ReturnNode = Node;\r
1203 }\r
1204\r
7936fb6a 1205 return EFI_SUCCESS;\r
1206 }\r
1207\r
1208 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1209 }\r
1210\r
1211 return EFI_NOT_FOUND;\r
1212}\r
1213\r
1214\r
1215/**\r
1216 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
1217\r
94f3aae7 1218 @param Storage The Storage to be conveted.\r
7936fb6a 1219 @param ConfigResp The returned <ConfigResp>.\r
94f3aae7 1220 @param ConfigRequest The ConfigRequest string.\r
7c6c064c 1221 @param GetEditBuf Get the data from editbuffer or buffer.\r
7936fb6a 1222\r
1223 @retval EFI_SUCCESS Convert success.\r
1224 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1225\r
1226**/\r
1227EFI_STATUS\r
1228StorageToConfigResp (\r
94f3aae7 1229 IN BROWSER_STORAGE *Storage,\r
b18e7050 1230 IN CHAR16 **ConfigResp,\r
7c6c064c
ED
1231 IN CHAR16 *ConfigRequest,\r
1232 IN BOOLEAN GetEditBuf\r
7936fb6a 1233 )\r
1234{\r
94f3aae7
ED
1235 EFI_STATUS Status;\r
1236 EFI_STRING Progress;\r
7936fb6a 1237 LIST_ENTRY *Link;\r
1238 NAME_VALUE_NODE *Node;\r
7c6c064c 1239 UINT8 *SourceBuf;\r
a35ecb75 1240 FORMSET_STORAGE *FormsetStorage;\r
7936fb6a 1241\r
1242 Status = EFI_SUCCESS;\r
1243\r
1244 switch (Storage->Type) {\r
1245 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 1246 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
7c6c064c 1247 SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;\r
7936fb6a 1248 Status = mHiiConfigRouting->BlockToConfig (\r
1249 mHiiConfigRouting,\r
b18e7050 1250 ConfigRequest,\r
7c6c064c 1251 SourceBuf,\r
7936fb6a 1252 Storage->Size,\r
1253 ConfigResp,\r
1254 &Progress\r
1255 );\r
1256 break;\r
1257\r
1258 case EFI_HII_VARSTORE_NAME_VALUE:\r
1259 *ConfigResp = NULL;\r
a35ecb75
ED
1260 FormsetStorage = GetFstStgFromBrsStg(Storage);\r
1261 ASSERT (FormsetStorage != NULL);\r
1262 NewStringCat (ConfigResp, FormsetStorage->ConfigHdr);\r
7936fb6a 1263\r
1264 Link = GetFirstNode (&Storage->NameValueListHead);\r
1265 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1266 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1267\r
b18e7050
ED
1268 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
1269 NewStringCat (ConfigResp, L"&");\r
1270 NewStringCat (ConfigResp, Node->Name);\r
1271 NewStringCat (ConfigResp, L"=");\r
7c6c064c
ED
1272 if (GetEditBuf) {\r
1273 NewStringCat (ConfigResp, Node->EditValue);\r
1274 } else {\r
1275 NewStringCat (ConfigResp, Node->Value);\r
1276 }\r
b18e7050 1277 }\r
7936fb6a 1278 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1279 }\r
1280 break;\r
1281\r
1282 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1283 default:\r
1284 Status = EFI_INVALID_PARAMETER;\r
1285 break;\r
1286 }\r
1287\r
1288 return Status;\r
1289}\r
1290\r
1291\r
1292/**\r
1293 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
1294\r
1295 @param Storage The Storage to receive the settings.\r
1296 @param ConfigResp The <ConfigResp> to be converted.\r
1297\r
1298 @retval EFI_SUCCESS Convert success.\r
1299 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1300\r
1301**/\r
1302EFI_STATUS\r
1303ConfigRespToStorage (\r
94f3aae7 1304 IN BROWSER_STORAGE *Storage,\r
7936fb6a 1305 IN CHAR16 *ConfigResp\r
1306 )\r
1307{\r
1308 EFI_STATUS Status;\r
1309 EFI_STRING Progress;\r
1310 UINTN BufferSize;\r
1311 CHAR16 *StrPtr;\r
1312 CHAR16 *Name;\r
1313 CHAR16 *Value;\r
1314\r
1315 Status = EFI_SUCCESS;\r
1316\r
1317 switch (Storage->Type) {\r
1318 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 1319 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
7936fb6a 1320 BufferSize = Storage->Size;\r
1321 Status = mHiiConfigRouting->ConfigToBlock (\r
1322 mHiiConfigRouting,\r
1323 ConfigResp,\r
1324 Storage->EditBuffer,\r
1325 &BufferSize,\r
1326 &Progress\r
1327 );\r
1328 break;\r
1329\r
1330 case EFI_HII_VARSTORE_NAME_VALUE:\r
40245175
LG
1331 StrPtr = StrStr (ConfigResp, L"PATH");\r
1332 if (StrPtr == NULL) {\r
1333 break;\r
1334 }\r
7936fb6a 1335 StrPtr = StrStr (ConfigResp, L"&");\r
1336 while (StrPtr != NULL) {\r
1337 //\r
1338 // Skip '&'\r
1339 //\r
1340 StrPtr = StrPtr + 1;\r
1341 Name = StrPtr;\r
1342 StrPtr = StrStr (StrPtr, L"=");\r
1343 if (StrPtr == NULL) {\r
1344 break;\r
1345 }\r
1346 *StrPtr = 0;\r
1347\r
1348 //\r
1349 // Skip '='\r
1350 //\r
1351 StrPtr = StrPtr + 1;\r
1352 Value = StrPtr;\r
1353 StrPtr = StrStr (StrPtr, L"&");\r
1354 if (StrPtr != NULL) {\r
1355 *StrPtr = 0;\r
1356 }\r
7c6c064c 1357 SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
7936fb6a 1358 }\r
1359 break;\r
1360\r
1361 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1362 default:\r
1363 Status = EFI_INVALID_PARAMETER;\r
1364 break;\r
1365 }\r
1366\r
1367 return Status;\r
1368}\r
1369\r
7a9612ce
ED
1370/**\r
1371 Convert the buffer value to HiiValue.\r
1372\r
1373 @param Question The question.\r
1374 @param Value Unicode buffer save the question value.\r
1375\r
1376 @retval Status whether convert the value success.\r
1377\r
1378**/\r
1379EFI_STATUS\r
1380BufferToValue (\r
1381 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1382 IN CHAR16 *Value\r
1383 )\r
1384{\r
1385 CHAR16 *StringPtr;\r
1386 BOOLEAN IsBufferStorage;\r
1387 CHAR16 *DstBuf;\r
1388 CHAR16 TempChar;\r
1389 UINTN LengthStr;\r
1390 UINT8 *Dst;\r
1391 CHAR16 TemStr[5];\r
1392 UINTN Index;\r
1393 UINT8 DigitUint8;\r
1394 BOOLEAN IsString;\r
1395 UINTN Length;\r
1396 EFI_STATUS Status;\r
1397\r
1398 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1399 if (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1400 Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1401 IsBufferStorage = TRUE;\r
1402 } else {\r
1403 IsBufferStorage = FALSE;\r
1404 }\r
1405\r
1406 //\r
1407 // Question Value is provided by Buffer Storage or NameValue Storage\r
1408 //\r
1409 if (Question->BufferValue != NULL) {\r
1410 //\r
1411 // This Question is password or orderedlist\r
1412 //\r
1413 Dst = Question->BufferValue;\r
1414 } else {\r
1415 //\r
1416 // Other type of Questions\r
1417 //\r
1418 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1419 }\r
1420\r
1421 //\r
1422 // Temp cut at the end of this section, end with '\0' or '&'.\r
1423 //\r
1424 StringPtr = Value;\r
1425 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1426 StringPtr++;\r
1427 }\r
1428 TempChar = *StringPtr;\r
1429 *StringPtr = L'\0';\r
1430\r
1431 LengthStr = StrLen (Value);\r
f3587039
DB
1432\r
1433 //\r
1434 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
1435 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
1436 // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
1437 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
1438 //\r
1439 if (LengthStr > (UINTN) Question->StorageWidth * 2) {\r
1440 Length = (UINTN) Question->StorageWidth * 2;\r
1441 } else {\r
1442 Length = LengthStr;\r
1443 }\r
1444\r
7a9612ce
ED
1445 Status = EFI_SUCCESS;\r
1446 if (!IsBufferStorage && IsString) {\r
1447 //\r
1448 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1449 // Add string tail char L'\0' into Length\r
1450 //\r
f3587039
DB
1451 DstBuf = (CHAR16 *) Dst;\r
1452 ZeroMem (TemStr, sizeof (TemStr));\r
1453 for (Index = 0; Index < Length; Index += 4) {\r
1454 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
1455 DstBuf[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
7a9612ce 1456 }\r
f3587039
DB
1457 //\r
1458 // Add tailing L'\0' character\r
1459 //\r
1460 DstBuf[Index/4] = L'\0';\r
7a9612ce 1461 } else {\r
f3587039
DB
1462 ZeroMem (TemStr, sizeof (TemStr));\r
1463 for (Index = 0; Index < Length; Index ++) {\r
1464 TemStr[0] = Value[LengthStr - Index - 1];\r
1465 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1466 if ((Index & 1) == 0) {\r
1467 Dst [Index/2] = DigitUint8;\r
1468 } else {\r
1469 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
7a9612ce
ED
1470 }\r
1471 }\r
1472 }\r
1473\r
1474 *StringPtr = TempChar;\r
1475\r
1476 return Status;\r
1477}\r
7936fb6a 1478\r
1479/**\r
1480 Get Question's current Value.\r
1481\r
1482 @param FormSet FormSet data structure.\r
1483 @param Form Form data structure.\r
1484 @param Question Question to be initialized.\r
816a7110 1485 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
7936fb6a 1486\r
1487 @retval EFI_SUCCESS The function completed successfully.\r
1488\r
1489**/\r
1490EFI_STATUS\r
1491GetQuestionValue (\r
1492 IN FORM_BROWSER_FORMSET *FormSet,\r
1493 IN FORM_BROWSER_FORM *Form,\r
1494 IN OUT FORM_BROWSER_STATEMENT *Question,\r
816a7110 1495 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
7936fb6a 1496 )\r
1497{\r
1498 EFI_STATUS Status;\r
1499 BOOLEAN Enabled;\r
1500 BOOLEAN Pending;\r
1501 UINT8 *Dst;\r
1502 UINTN StorageWidth;\r
1503 EFI_TIME EfiTime;\r
94f3aae7 1504 BROWSER_STORAGE *Storage;\r
a35ecb75 1505 FORMSET_STORAGE *FormsetStorage;\r
7936fb6a 1506 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1507 CHAR16 *ConfigRequest;\r
1508 CHAR16 *Progress;\r
1509 CHAR16 *Result;\r
1510 CHAR16 *Value;\r
1511 UINTN Length;\r
1512 BOOLEAN IsBufferStorage;\r
5ad66ec6 1513 UINTN MaxLen;\r
7936fb6a 1514\r
1515 Status = EFI_SUCCESS;\r
cce6230f 1516 Value = NULL;\r
db40504e 1517 Result = NULL;\r
7936fb6a 1518\r
816a7110
ED
1519 if (GetValueFrom >= GetSetValueWithMax) {\r
1520 return EFI_INVALID_PARAMETER;\r
1521 }\r
1522\r
7936fb6a 1523 //\r
1524 // Question value is provided by an Expression, evaluate it\r
1525 //\r
1526 if (Question->ValueExpression != NULL) {\r
1527 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1528 if (!EFI_ERROR (Status)) {\r
901ba0e7
ED
1529 if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1530 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1531 if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
1532 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
1533 Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
1534 } else {\r
1535 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
1536 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1537 }\r
1538 FreePool (Question->ValueExpression->Result.Buffer);\r
1539 }\r
1540 Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
1541 CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 1542 }\r
1543 return Status;\r
1544 }\r
2573712e
LG
1545 \r
1546 //\r
1547 // Get question value by read expression.\r
1548 //\r
1549 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1550 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
901ba0e7
ED
1551 if (!EFI_ERROR (Status) && \r
1552 ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {\r
2573712e
LG
1553 //\r
1554 // Only update question value to the valid result.\r
1555 //\r
901ba0e7
ED
1556 if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1557 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1558 if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
1559 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
1560 Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
1561 } else {\r
1562 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
1563 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1564 }\r
1565 FreePool (Question->ReadExpression->Result.Buffer);\r
1566 }\r
1567 Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
1568 CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
2573712e
LG
1569 return EFI_SUCCESS;\r
1570 }\r
1571 }\r
7936fb6a 1572\r
1573 //\r
1574 // Question value is provided by RTC\r
1575 //\r
1576 Storage = Question->Storage;\r
1577 QuestionValue = &Question->HiiValue.Value;\r
1578 if (Storage == NULL) {\r
1579 //\r
1580 // It's a Question without storage, or RTC date/time\r
1581 //\r
1582 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1583 //\r
1584 // Date and time define the same Flags bit\r
1585 //\r
1586 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1587 case QF_DATE_STORAGE_TIME:\r
1588 Status = gRT->GetTime (&EfiTime, NULL);\r
1589 break;\r
1590\r
1591 case QF_DATE_STORAGE_WAKEUP:\r
1592 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1593 break;\r
1594\r
1595 case QF_DATE_STORAGE_NORMAL:\r
1596 default:\r
1597 //\r
1598 // For date/time without storage\r
1599 //\r
1600 return EFI_SUCCESS;\r
1601 }\r
1602\r
1603 if (EFI_ERROR (Status)) {\r
cc63add8
DB
1604 if (Question->Operand == EFI_IFR_DATE_OP){\r
1605 QuestionValue->date.Year = 0xff;\r
1606 QuestionValue->date.Month = 0xff;\r
1607 QuestionValue->date.Day = 0xff;\r
1608 } else {\r
1609 QuestionValue->time.Hour = 0xff;\r
1610 QuestionValue->time.Minute = 0xff;\r
1611 QuestionValue->time.Second = 0xff;\r
1612 }\r
1613 return EFI_SUCCESS;\r
7936fb6a 1614 }\r
1615\r
1616 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1617 QuestionValue->date.Year = EfiTime.Year;\r
1618 QuestionValue->date.Month = EfiTime.Month;\r
1619 QuestionValue->date.Day = EfiTime.Day;\r
1620 } else {\r
1621 QuestionValue->time.Hour = EfiTime.Hour;\r
1622 QuestionValue->time.Minute = EfiTime.Minute;\r
1623 QuestionValue->time.Second = EfiTime.Second;\r
1624 }\r
1625 }\r
1626\r
1627 return EFI_SUCCESS;\r
1628 }\r
1629\r
1630 //\r
1631 // Question value is provided by EFI variable\r
1632 //\r
1633 StorageWidth = Question->StorageWidth;\r
1634 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1635 if (Question->BufferValue != NULL) {\r
1636 Dst = Question->BufferValue;\r
1637 } else {\r
1638 Dst = (UINT8 *) QuestionValue;\r
1639 }\r
1640\r
1641 Status = gRT->GetVariable (\r
1642 Question->VariableName,\r
1643 &Storage->Guid,\r
1644 NULL,\r
1645 &StorageWidth,\r
1646 Dst\r
1647 );\r
1648 //\r
1649 // Always return success, even this EFI variable doesn't exist\r
1650 //\r
1651 return EFI_SUCCESS;\r
1652 }\r
1653\r
1654 //\r
1655 // Question Value is provided by Buffer Storage or NameValue Storage\r
1656 //\r
1657 if (Question->BufferValue != NULL) {\r
1658 //\r
1659 // This Question is password or orderedlist\r
1660 //\r
1661 Dst = Question->BufferValue;\r
1662 } else {\r
1663 //\r
1664 // Other type of Questions\r
1665 //\r
1666 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1667 }\r
1668\r
cce6230f
ED
1669 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1670 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1671 IsBufferStorage = TRUE;\r
1672 } else {\r
1673 IsBufferStorage = FALSE;\r
1674 }\r
816a7110 1675 if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {\r
7936fb6a 1676 if (IsBufferStorage) {\r
816a7110
ED
1677 if (GetValueFrom == GetSetValueWithEditBuffer) {\r
1678 //\r
1679 // Copy from storage Edit buffer\r
1680 //\r
1681 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1682 } else {\r
1683 //\r
1684 // Copy from storage Edit buffer\r
1685 //\r
1686 CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1687 }\r
7936fb6a 1688 } else {\r
1b2bf3ca 1689 Value = NULL;\r
816a7110 1690 Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
7936fb6a 1691 if (EFI_ERROR (Status)) {\r
1692 return Status;\r
1693 }\r
d66e6c16 1694\r
1b2bf3ca 1695 ASSERT (Value != NULL);\r
7a9612ce 1696 Status = BufferToValue (Question, Value);\r
f4113e1f 1697 FreePool (Value);\r
7936fb6a 1698 }\r
1699 } else {\r
a35ecb75
ED
1700 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
1701 ASSERT (FormsetStorage != NULL);\r
7248790e
ED
1702 //\r
1703 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1704 // <ConfigHdr> + "&" + <VariableName>\r
1705 //\r
1706 if (IsBufferStorage) {\r
a35ecb75 1707 Length = StrLen (FormsetStorage->ConfigHdr);\r
7248790e
ED
1708 Length += StrLen (Question->BlockName);\r
1709 } else {\r
a35ecb75 1710 Length = StrLen (FormsetStorage->ConfigHdr);\r
7248790e
ED
1711 Length += StrLen (Question->VariableName) + 1;\r
1712 }\r
5ad66ec6
DB
1713 // Allocate buffer include '\0'\r
1714 MaxLen = Length + 1;\r
1715 ConfigRequest = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7248790e 1716 ASSERT (ConfigRequest != NULL);\r
7936fb6a 1717\r
5ad66ec6 1718 StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);\r
7248790e 1719 if (IsBufferStorage) {\r
5ad66ec6 1720 StrCatS (ConfigRequest, MaxLen, Question->BlockName);\r
7248790e 1721 } else {\r
5ad66ec6
DB
1722 StrCatS (ConfigRequest, MaxLen, L"&");\r
1723 StrCatS (ConfigRequest, MaxLen, Question->VariableName);\r
7248790e 1724 }\r
7936fb6a 1725\r
7248790e
ED
1726 //\r
1727 // Request current settings from Configuration Driver\r
1728 //\r
1729 Status = mHiiConfigRouting->ExtractConfig (\r
1730 mHiiConfigRouting,\r
1731 ConfigRequest,\r
1732 &Progress,\r
1733 &Result\r
1734 );\r
1735 FreePool (ConfigRequest);\r
1736 if (EFI_ERROR (Status)) {\r
1737 return Status;\r
1738 }\r
7936fb6a 1739\r
7248790e
ED
1740 //\r
1741 // Skip <ConfigRequest>\r
1742 //\r
1743 if (IsBufferStorage) {\r
1744 Value = StrStr (Result, L"&VALUE");\r
1745 if (Value == NULL) {\r
cce6230f
ED
1746 FreePool (Result);\r
1747 return EFI_NOT_FOUND;\r
1748 }\r
1749 //\r
7248790e 1750 // Skip "&VALUE"\r
cce6230f 1751 //\r
7248790e
ED
1752 Value = Value + 6;\r
1753 } else {\r
1754 Value = Result + Length;\r
1755 }\r
1756 if (*Value != '=') {\r
1757 FreePool (Result);\r
1758 return EFI_NOT_FOUND;\r
1759 }\r
1760 //\r
1761 // Skip '=', point to value\r
1762 //\r
1763 Value = Value + 1;\r
1764\r
7a9612ce 1765 Status = BufferToValue (Question, Value);\r
7248790e
ED
1766 if (EFI_ERROR (Status)) {\r
1767 FreePool (Result);\r
1768 return Status;\r
63d55bb9
LG
1769 }\r
1770\r
7936fb6a 1771 //\r
1772 // Synchronize Edit Buffer\r
1773 //\r
1774 if (IsBufferStorage) {\r
1775 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1776 } else {\r
7c6c064c 1777 SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
7936fb6a 1778 }\r
db40504e
ED
1779\r
1780 if (Result != NULL) {\r
1781 FreePool (Result);\r
1782 }\r
7936fb6a 1783 }\r
1784\r
1785 return Status;\r
1786}\r
1787\r
1788\r
1789/**\r
1790 Save Question Value to edit copy(cached) or Storage(uncached).\r
1791\r
1792 @param FormSet FormSet data structure.\r
1793 @param Form Form data structure.\r
1794 @param Question Pointer to the Question.\r
816a7110 1795 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.\r
7936fb6a 1796\r
1797 @retval EFI_SUCCESS The function completed successfully.\r
1798\r
1799**/\r
1800EFI_STATUS\r
1801SetQuestionValue (\r
1802 IN FORM_BROWSER_FORMSET *FormSet,\r
1803 IN FORM_BROWSER_FORM *Form,\r
1804 IN OUT FORM_BROWSER_STATEMENT *Question,\r
816a7110 1805 IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
7936fb6a 1806 )\r
1807{\r
1808 EFI_STATUS Status;\r
1809 BOOLEAN Enabled;\r
1810 BOOLEAN Pending;\r
1811 UINT8 *Src;\r
1812 EFI_TIME EfiTime;\r
1813 UINTN BufferLen;\r
1814 UINTN StorageWidth;\r
94f3aae7 1815 BROWSER_STORAGE *Storage;\r
a35ecb75 1816 FORMSET_STORAGE *FormsetStorage;\r
7936fb6a 1817 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1818 CHAR16 *ConfigResp;\r
1819 CHAR16 *Progress;\r
1820 CHAR16 *Value;\r
1821 UINTN Length;\r
1822 BOOLEAN IsBufferStorage;\r
1823 BOOLEAN IsString;\r
63d55bb9
LG
1824 UINT8 *TemBuffer;\r
1825 CHAR16 *TemName;\r
1826 CHAR16 *TemString;\r
1827 UINTN Index;\r
7c6c064c 1828 NAME_VALUE_NODE *Node;\r
5ad66ec6 1829 UINTN MaxLen;\r
7936fb6a 1830\r
1831 Status = EFI_SUCCESS;\r
7c6c064c 1832 Node = NULL;\r
7936fb6a 1833\r
816a7110
ED
1834 if (SetValueTo >= GetSetValueWithMax) {\r
1835 return EFI_INVALID_PARAMETER;\r
1836 }\r
1837\r
7936fb6a 1838 //\r
1839 // If Question value is provided by an Expression, then it is read only\r
1840 //\r
1841 if (Question->ValueExpression != NULL) {\r
1842 return Status;\r
1843 }\r
2573712e
LG
1844 \r
1845 //\r
1846 // Before set question value, evaluate its write expression.\r
1847 //\r
1848 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1849 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1850 if (EFI_ERROR (Status)) {\r
1851 return Status;\r
1852 }\r
1853 }\r
7936fb6a 1854\r
1855 //\r
1856 // Question value is provided by RTC\r
1857 //\r
1858 Storage = Question->Storage;\r
1859 QuestionValue = &Question->HiiValue.Value;\r
1860 if (Storage == NULL) {\r
1861 //\r
1862 // It's a Question without storage, or RTC date/time\r
1863 //\r
1864 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1865 //\r
1866 // Date and time define the same Flags bit\r
1867 //\r
1868 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1869 case QF_DATE_STORAGE_TIME:\r
1870 Status = gRT->GetTime (&EfiTime, NULL);\r
1871 break;\r
1872\r
1873 case QF_DATE_STORAGE_WAKEUP:\r
1874 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1875 break;\r
1876\r
1877 case QF_DATE_STORAGE_NORMAL:\r
1878 default:\r
1879 //\r
1880 // For date/time without storage\r
1881 //\r
1882 return EFI_SUCCESS;\r
1883 }\r
1884\r
1885 if (EFI_ERROR (Status)) {\r
1886 return Status;\r
1887 }\r
1888\r
1889 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1890 EfiTime.Year = QuestionValue->date.Year;\r
1891 EfiTime.Month = QuestionValue->date.Month;\r
1892 EfiTime.Day = QuestionValue->date.Day;\r
1893 } else {\r
1894 EfiTime.Hour = QuestionValue->time.Hour;\r
1895 EfiTime.Minute = QuestionValue->time.Minute;\r
1896 EfiTime.Second = QuestionValue->time.Second;\r
1897 }\r
1898\r
1899 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1900 Status = gRT->SetTime (&EfiTime);\r
1901 } else {\r
1902 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1903 }\r
1904 }\r
1905\r
1906 return Status;\r
1907 }\r
1908\r
1909 //\r
1910 // Question value is provided by EFI variable\r
1911 //\r
1912 StorageWidth = Question->StorageWidth;\r
1913 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1914 if (Question->BufferValue != NULL) {\r
1915 Src = Question->BufferValue;\r
1916 } else {\r
1917 Src = (UINT8 *) QuestionValue;\r
1918 }\r
1919\r
1920 Status = gRT->SetVariable (\r
1921 Question->VariableName,\r
1922 &Storage->Guid,\r
1923 Storage->Attributes,\r
1924 StorageWidth,\r
1925 Src\r
1926 );\r
1927 return Status;\r
1928 }\r
1929\r
1930 //\r
1931 // Question Value is provided by Buffer Storage or NameValue Storage\r
1932 //\r
1933 if (Question->BufferValue != NULL) {\r
1934 Src = Question->BufferValue;\r
1935 } else {\r
1936 Src = (UINT8 *) &Question->HiiValue.Value;\r
1937 }\r
1938\r
cce6230f
ED
1939 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1940 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1941 IsBufferStorage = TRUE;\r
1942 } else {\r
1943 IsBufferStorage = FALSE;\r
1944 }\r
7936fb6a 1945 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
816a7110
ED
1946\r
1947 if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {\r
1948 if (IsBufferStorage) {\r
1949 if (SetValueTo == GetSetValueWithEditBuffer) {\r
1950 //\r
1951 // Copy to storage edit buffer\r
1952 // \r
1953 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1954 } else if (SetValueTo == GetSetValueWithBuffer) {\r
1955 //\r
1956 // Copy to storage edit buffer\r
1957 // \r
1958 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
63d55bb9 1959 }\r
7936fb6a 1960 } else {\r
816a7110
ED
1961 if (IsString) {\r
1962 //\r
1963 // Allocate enough string buffer.\r
1964 //\r
1965 Value = NULL;\r
1966 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1967 Value = AllocateZeroPool (BufferLen);\r
1968 ASSERT (Value != NULL);\r
1969 //\r
1970 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1971 //\r
1972 TemName = (CHAR16 *) Src;\r
1973 TemString = Value;\r
1974 for (; *TemName != L'\0'; TemName++) {\r
1975 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1976 }\r
1977 } else {\r
1978 BufferLen = StorageWidth * 2 + 1;\r
1979 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1980 ASSERT (Value != NULL);\r
1981 //\r
1982 // Convert Buffer to Hex String\r
1983 //\r
1984 TemBuffer = Src + StorageWidth - 1;\r
1985 TemString = Value;\r
1986 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1987 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1988 }\r
63d55bb9 1989 }\r
7936fb6a 1990\r
7c6c064c 1991 Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
816a7110 1992 FreePool (Value);\r
7c6c064c
ED
1993 if (EFI_ERROR (Status)) {\r
1994 return Status;\r
1995 }\r
816a7110
ED
1996 }\r
1997 } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
7248790e
ED
1998 //\r
1999 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
2000 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
2001 //\r
2002 if (IsBufferStorage) {\r
2003 Length = StrLen (Question->BlockName) + 7;\r
2004 } else {\r
2005 Length = StrLen (Question->VariableName) + 2;\r
2006 }\r
2007 if (!IsBufferStorage && IsString) {\r
2008 Length += (StrLen ((CHAR16 *) Src) * 4);\r
2009 } else {\r
2010 Length += (StorageWidth * 2);\r
2011 }\r
a35ecb75
ED
2012 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
2013 ASSERT (FormsetStorage != NULL);\r
5ad66ec6
DB
2014 MaxLen = StrLen (FormsetStorage->ConfigHdr) + Length + 1;\r
2015 ConfigResp = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7248790e 2016 ASSERT (ConfigResp != NULL);\r
7936fb6a 2017\r
5ad66ec6 2018 StrCpyS (ConfigResp, MaxLen, FormsetStorage->ConfigHdr);\r
7248790e 2019 if (IsBufferStorage) {\r
5ad66ec6
DB
2020 StrCatS (ConfigResp, MaxLen, Question->BlockName);\r
2021 StrCatS (ConfigResp, MaxLen, L"&VALUE=");\r
7248790e 2022 } else {\r
5ad66ec6
DB
2023 StrCatS (ConfigResp, MaxLen, L"&");\r
2024 StrCatS (ConfigResp, MaxLen, Question->VariableName);\r
2025 StrCatS (ConfigResp, MaxLen, L"=");\r
7248790e 2026 }\r
cce6230f 2027\r
7248790e 2028 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 2029\r
7248790e 2030 if (!IsBufferStorage && IsString) {\r
7936fb6a 2031 //\r
7248790e 2032 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
7936fb6a 2033 //\r
7248790e
ED
2034 TemName = (CHAR16 *) Src;\r
2035 TemString = Value;\r
2036 for (; *TemName != L'\0'; TemName++) {\r
2037 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
63d55bb9 2038 }\r
7248790e 2039 } else {\r
63d55bb9 2040 //\r
7248790e 2041 // Convert Buffer to Hex String\r
63d55bb9 2042 //\r
7248790e
ED
2043 TemBuffer = Src + StorageWidth - 1;\r
2044 TemString = Value;\r
2045 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
2046 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
63d55bb9 2047 }\r
7248790e
ED
2048 }\r
2049\r
2050 //\r
2051 // Convert to lower char.\r
2052 //\r
2053 for (TemString = Value; *Value != L'\0'; Value++) {\r
2054 if (*Value >= L'A' && *Value <= L'Z') {\r
2055 *Value = (CHAR16) (*Value - L'A' + L'a');\r
7936fb6a 2056 }\r
2057 }\r
7248790e
ED
2058\r
2059 //\r
2060 // Submit Question Value to Configuration Driver\r
2061 //\r
2062 Status = mHiiConfigRouting->RouteConfig (\r
2063 mHiiConfigRouting,\r
2064 ConfigResp,\r
2065 &Progress\r
2066 );\r
2067 if (EFI_ERROR (Status)) {\r
2068 FreePool (ConfigResp);\r
2069 return Status;\r
2070 }\r
2071 FreePool (ConfigResp);\r
2072 \r
7936fb6a 2073 //\r
cce6230f 2074 // Sync storage, from editbuffer to buffer.\r
7936fb6a 2075 //\r
cce6230f 2076 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
7936fb6a 2077 }\r
2078\r
2079 return Status;\r
2080}\r
2081\r
2082\r
2083/**\r
7c6c064c 2084 Perform nosubmitif check for a Form.\r
7936fb6a 2085\r
2086 @param FormSet FormSet data structure.\r
2087 @param Form Form data structure.\r
2088 @param Question The Question to be validated.\r
7c6c064c 2089 @param Type Validation type: NoSubmit\r
7936fb6a 2090\r
2091 @retval EFI_SUCCESS Form validation pass.\r
2092 @retval other Form validation failed.\r
2093\r
2094**/\r
2095EFI_STATUS\r
2096ValidateQuestion (\r
2097 IN FORM_BROWSER_FORMSET *FormSet,\r
2098 IN FORM_BROWSER_FORM *Form,\r
2099 IN FORM_BROWSER_STATEMENT *Question,\r
2100 IN UINTN Type\r
2101 )\r
2102{\r
2103 EFI_STATUS Status;\r
2104 LIST_ENTRY *Link;\r
2105 LIST_ENTRY *ListHead;\r
7936fb6a 2106 FORM_EXPRESSION *Expression;\r
bfae1330
ED
2107 UINT32 BrowserStatus;\r
2108 CHAR16 *ErrorStr;\r
2109\r
2110 BrowserStatus = BROWSER_SUCCESS;\r
2111 ErrorStr = NULL;\r
2112\r
2113 switch (Type) {\r
2114 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2115 ListHead = &Question->InconsistentListHead;\r
2116 break;\r
7936fb6a 2117\r
bfae1330
ED
2118 case EFI_HII_EXPRESSION_WARNING_IF:\r
2119 ListHead = &Question->WarningListHead;\r
2120 break;\r
2121\r
2122 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
7936fb6a 2123 ListHead = &Question->NoSubmitListHead;\r
bfae1330
ED
2124 break;\r
2125\r
2126 default:\r
2127 ASSERT (FALSE);\r
7936fb6a 2128 return EFI_UNSUPPORTED;\r
2129 }\r
2130\r
2131 Link = GetFirstNode (ListHead);\r
2132 while (!IsNull (ListHead, Link)) {\r
2133 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
2134\r
2135 //\r
2136 // Evaluate the expression\r
2137 //\r
2138 Status = EvaluateExpression (FormSet, Form, Expression);\r
2139 if (EFI_ERROR (Status)) {\r
2140 return Status;\r
2141 }\r
2142\r
e6106e89 2143 if (IsTrue (&Expression->Result)) {\r
bfae1330
ED
2144 switch (Type) {\r
2145 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2146 BrowserStatus = BROWSER_INCONSISTENT_IF;\r
2147 break;\r
2148\r
2149 case EFI_HII_EXPRESSION_WARNING_IF:\r
2150 BrowserStatus = BROWSER_WARNING_IF;\r
2151 break;\r
2152\r
2153 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
2154 BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
2155 //\r
2156 // This code only used to compatible with old display engine,\r
2157 // New display engine will not use this field.\r
2158 //\r
2159 if (Expression->Error != 0) {\r
2160 ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
7c6c064c 2161 }\r
bfae1330
ED
2162 break;\r
2163\r
2164 default:\r
2165 ASSERT (FALSE);\r
2166 break;\r
7936fb6a 2167 }\r
2168\r
4d4deaac
ED
2169 if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
2170 //\r
2171 // If in system submit process and for no_submit_if check, not popup this error message.\r
2172 // Will process this fail again later in not system submit process.\r
2173 //\r
2174 PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
2175 }\r
bfae1330
ED
2176\r
2177 if (ErrorStr != NULL) {\r
2178 FreePool (ErrorStr);\r
2179 }\r
2180\r
2181 if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
2182 return EFI_SUCCESS;\r
2183 } else {\r
2184 return EFI_NOT_READY;\r
2185 }\r
7936fb6a 2186 }\r
2187\r
2188 Link = GetNextNode (ListHead, Link);\r
2189 }\r
2190\r
2191 return EFI_SUCCESS;\r
2192}\r
2193\r
bfae1330
ED
2194/**\r
2195 Perform question check. \r
2196 \r
2197 If one question has more than one check, process form high priority to low. \r
2198 Only one error info will be popup.\r
2199\r
2200 @param FormSet FormSet data structure.\r
2201 @param Form Form data structure.\r
2202 @param Question The Question to be validated.\r
2203\r
2204 @retval EFI_SUCCESS Form validation pass.\r
2205 @retval other Form validation failed.\r
2206\r
2207**/\r
2208EFI_STATUS\r
2209ValueChangedValidation (\r
2210 IN FORM_BROWSER_FORMSET *FormSet,\r
2211 IN FORM_BROWSER_FORM *Form,\r
2212 IN FORM_BROWSER_STATEMENT *Question\r
2213 )\r
2214{\r
2215 EFI_STATUS Status;\r
2216\r
2217 Status = EFI_SUCCESS;\r
2218\r
2219 //\r
2220 // Do the inconsistentif check.\r
2221 //\r
2222 if (!IsListEmpty (&Question->InconsistentListHead)) {\r
2223 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
2224 if (EFI_ERROR (Status)) {\r
2225 return Status;\r
2226 }\r
2227 }\r
2228\r
2229 //\r
2230 // Do the warningif check.\r
2231 //\r
2232 if (!IsListEmpty (&Question->WarningListHead)) {\r
2233 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
2234 }\r
2235\r
2236 return Status;\r
2237}\r
7936fb6a 2238\r
2239/**\r
5adb8db7 2240 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 2241\r
2242 @param FormSet FormSet data structure.\r
b18e7050 2243 @param CurrentForm Current input form data structure.\r
4d4deaac 2244 @param Statement The statement for this check.\r
7936fb6a 2245\r
2246 @retval EFI_SUCCESS Form validation pass.\r
2247 @retval other Form validation failed.\r
2248\r
2249**/\r
2250EFI_STATUS\r
2251NoSubmitCheck (\r
4d4deaac
ED
2252 IN FORM_BROWSER_FORMSET *FormSet,\r
2253 IN OUT FORM_BROWSER_FORM **CurrentForm,\r
2254 OUT FORM_BROWSER_STATEMENT **Statement\r
7936fb6a 2255 )\r
2256{\r
2257 EFI_STATUS Status;\r
2258 LIST_ENTRY *Link;\r
2259 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
2260 FORM_BROWSER_FORM *Form;\r
2261 LIST_ENTRY *LinkForm;\r
7936fb6a 2262\r
5adb8db7
LG
2263 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
2264 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
2265 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
2266 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
2267\r
4d4deaac 2268 if (*CurrentForm != NULL && *CurrentForm != Form) {\r
b18e7050
ED
2269 continue;\r
2270 }\r
7936fb6a 2271\r
5adb8db7
LG
2272 Link = GetFirstNode (&Form->StatementListHead);\r
2273 while (!IsNull (&Form->StatementListHead, Link)) {\r
2274 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
5adb8db7
LG
2275 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2276 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
2277 if (*CurrentForm == NULL) {\r
2278 *CurrentForm = Form;\r
2279 }\r
2280 if (Statement != NULL) {\r
2281 *Statement = Question;\r
2282 }\r
5adb8db7
LG
2283 return Status;\r
2284 }\r
2285\r
2286 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 2287 }\r
7936fb6a 2288 }\r
2289\r
2290 return EFI_SUCCESS;\r
2291}\r
2292\r
7936fb6a 2293/**\r
b18e7050
ED
2294 Fill storage's edit copy with settings requested from Configuration Driver.\r
2295\r
7c6c064c
ED
2296 @param Storage The storage which need to sync.\r
2297 @param ConfigRequest The config request string which used to sync storage.\r
cce6230f
ED
2298 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2299 editbuffer to buffer\r
2300 if TRUE, copy the editbuffer to the buffer.\r
2301 if FALSE, copy the buffer to the editbuffer.\r
b18e7050
ED
2302\r
2303 @retval EFI_SUCCESS The function completed successfully.\r
2304\r
2305**/\r
2306EFI_STATUS\r
7c6c064c 2307SynchronizeStorage (\r
7c6c064c
ED
2308 OUT BROWSER_STORAGE *Storage,\r
2309 IN CHAR16 *ConfigRequest,\r
2310 IN BOOLEAN SyncOrRestore\r
b18e7050
ED
2311 )\r
2312{\r
2313 EFI_STATUS Status;\r
2314 EFI_STRING Progress;\r
2315 EFI_STRING Result;\r
2316 UINTN BufferSize;\r
2317 LIST_ENTRY *Link;\r
2318 NAME_VALUE_NODE *Node;\r
cce6230f
ED
2319 UINT8 *Src;\r
2320 UINT8 *Dst;\r
b18e7050
ED
2321\r
2322 Status = EFI_SUCCESS;\r
2323 Result = NULL;\r
25361615 2324\r
7c6c064c
ED
2325 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2326 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
2327 BufferSize = Storage->Size;\r
cce6230f
ED
2328\r
2329 if (SyncOrRestore) {\r
7c6c064c
ED
2330 Src = Storage->EditBuffer;\r
2331 Dst = Storage->Buffer;\r
cce6230f 2332 } else {\r
7c6c064c
ED
2333 Src = Storage->Buffer;\r
2334 Dst = Storage->EditBuffer;\r
cce6230f
ED
2335 }\r
2336\r
7c6c064c
ED
2337 if (ConfigRequest != NULL) {\r
2338 Status = mHiiConfigRouting->BlockToConfig(\r
2339 mHiiConfigRouting,\r
2340 ConfigRequest,\r
2341 Src,\r
2342 BufferSize,\r
2343 &Result,\r
2344 &Progress\r
2345 );\r
2346 if (EFI_ERROR (Status)) {\r
2347 return Status;\r
2348 }\r
b18e7050 2349\r
7c6c064c
ED
2350 Status = mHiiConfigRouting->ConfigToBlock (\r
2351 mHiiConfigRouting,\r
2352 Result,\r
2353 Dst,\r
2354 &BufferSize,\r
2355 &Progress\r
2356 );\r
2357 if (Result != NULL) {\r
2358 FreePool (Result);\r
2359 }\r
2360 } else {\r
2361 CopyMem (Dst, Src, BufferSize);\r
b18e7050 2362 }\r
7c6c064c
ED
2363 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2364 Link = GetFirstNode (&Storage->NameValueListHead);\r
2365 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
b18e7050
ED
2366 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2367\r
7c6c064c
ED
2368 if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
2369 (ConfigRequest == NULL)) {\r
cce6230f
ED
2370 if (SyncOrRestore) {\r
2371 NewStringCpy (&Node->Value, Node->EditValue);\r
2372 } else {\r
2373 NewStringCpy (&Node->EditValue, Node->Value);\r
b18e7050 2374 }\r
b18e7050
ED
2375 }\r
2376\r
7c6c064c 2377 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
b18e7050
ED
2378 }\r
2379 }\r
2380\r
2381 return Status;\r
2382}\r
2383\r
816a7110
ED
2384/**\r
2385 When discard the question value, call the callback function with Changed type\r
2386 to inform the hii driver.\r
2387\r
2388 @param FormSet FormSet data structure.\r
2389 @param Form Form data structure.\r
2390\r
2391**/\r
2392VOID\r
2393SendDiscardInfoToDriver (\r
2394 IN FORM_BROWSER_FORMSET *FormSet,\r
2395 IN FORM_BROWSER_FORM *Form\r
2396 )\r
2397{\r
2398 LIST_ENTRY *Link;\r
2399 FORM_BROWSER_STATEMENT *Question;\r
816a7110
ED
2400 EFI_IFR_TYPE_VALUE *TypeValue;\r
2401 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2402\r
70f1d5e7
ED
2403 if (FormSet->ConfigAccess == NULL) {\r
2404 return;\r
2405 }\r
2406\r
816a7110
ED
2407 Link = GetFirstNode (&Form->StatementListHead);\r
2408 while (!IsNull (&Form->StatementListHead, Link)) {\r
2409 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2410 Link = GetNextNode (&Form->StatementListHead, Link);\r
2411\r
2412 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2413 continue;\r
2414 }\r
2415\r
e213ae45
ED
2416 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2417 continue;\r
2418 }\r
2419\r
816a7110
ED
2420 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2421 continue;\r
2422 }\r
2423\r
7c6c064c 2424 if (!Question->ValueChanged) {\r
816a7110
ED
2425 continue;\r
2426 }\r
2427\r
737adca3
ED
2428 //\r
2429 // Restore the question value before call the CHANGED callback type.\r
2430 //\r
2431 GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
2432\r
cb312fb1
DB
2433 if (Question->Operand == EFI_IFR_STRING_OP){\r
2434 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
2435 }\r
2436\r
816a7110
ED
2437 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2438 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2439 } else {\r
2440 TypeValue = &Question->HiiValue.Value;\r
2441 }\r
2442\r
2443 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2444 FormSet->ConfigAccess->Callback (\r
2445 FormSet->ConfigAccess,\r
2446 EFI_BROWSER_ACTION_CHANGED,\r
2447 Question->QuestionId,\r
2448 Question->HiiValue.Type,\r
2449 TypeValue,\r
2450 &ActionRequest\r
2451 );\r
2452 }\r
2453}\r
b18e7050 2454\r
3cb44c20
DB
2455/**\r
2456 When submit the question value, call the callback function with Submitted type\r
2457 to inform the hii driver.\r
2458\r
2459 @param FormSet FormSet data structure.\r
2460 @param Form Form data structure.\r
2461\r
2462**/\r
2463VOID\r
2464SubmitCallbackForForm (\r
2465 IN FORM_BROWSER_FORMSET *FormSet,\r
2466 IN FORM_BROWSER_FORM *Form\r
2467 )\r
2468{\r
2469 LIST_ENTRY *Link;\r
2470 FORM_BROWSER_STATEMENT *Question;\r
2471 EFI_IFR_TYPE_VALUE *TypeValue;\r
2472 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2473\r
2474 if (FormSet->ConfigAccess == NULL) {\r
2475 return;\r
2476 }\r
2477\r
2478 Link = GetFirstNode (&Form->StatementListHead);\r
2479 while (!IsNull (&Form->StatementListHead, Link)) {\r
2480 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2481 Link = GetNextNode (&Form->StatementListHead, Link);\r
2482\r
2483 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2484 continue;\r
2485 }\r
2486\r
2487 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2488 continue;\r
2489 }\r
2490\r
2491 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2492 continue;\r
2493 }\r
2494\r
2495 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2496 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2497 } else {\r
2498 TypeValue = &Question->HiiValue.Value;\r
2499 }\r
2500\r
2501 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2502 FormSet->ConfigAccess->Callback (\r
2503 FormSet->ConfigAccess,\r
2504 EFI_BROWSER_ACTION_SUBMITTED,\r
2505 Question->QuestionId,\r
2506 Question->HiiValue.Type,\r
2507 TypeValue,\r
2508 &ActionRequest\r
2509 );\r
2510 }\r
2511}\r
2512\r
2513/**\r
2514 When value set Success, call the submit callback function.\r
2515\r
2516 @param FormSet FormSet data structure.\r
2517 @param Form Form data structure.\r
2518\r
2519**/\r
2520VOID\r
2521SubmitCallback (\r
2522 IN FORM_BROWSER_FORMSET *FormSet,\r
2523 IN FORM_BROWSER_FORM *Form\r
2524 )\r
2525{\r
2526 FORM_BROWSER_FORM *CurrentForm;\r
2527 LIST_ENTRY *Link;\r
2528\r
2529 if (Form != NULL) {\r
2530 SubmitCallbackForForm(FormSet, Form);\r
2531 return;\r
2532 }\r
2533\r
2534 Link = GetFirstNode (&FormSet->FormListHead);\r
2535 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2536 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2537 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2538\r
2539 SubmitCallbackForForm(FormSet, CurrentForm);\r
2540 }\r
2541}\r
2542\r
938baa1f 2543/**\r
dcca25d1 2544 Validate the HiiHandle.\r
938baa1f 2545\r
dcca25d1 2546 @param HiiHandle The input HiiHandle which need to validate.\r
938baa1f
ED
2547\r
2548 @retval TRUE The handle is validate.\r
2549 @retval FALSE The handle is invalidate.\r
2550\r
2551**/\r
2552BOOLEAN\r
93551a01
ED
2553ValidateHiiHandle (\r
2554 EFI_HII_HANDLE HiiHandle\r
938baa1f
ED
2555 )\r
2556{\r
2557 EFI_HII_HANDLE *HiiHandles;\r
2558 UINTN Index;\r
2559 BOOLEAN Find;\r
2560\r
93551a01
ED
2561 if (HiiHandle == NULL) {\r
2562 return FALSE;\r
2563 }\r
2564\r
938baa1f 2565 Find = FALSE;\r
93551a01 2566\r
938baa1f
ED
2567 HiiHandles = HiiGetHiiHandles (NULL);\r
2568 ASSERT (HiiHandles != NULL);\r
2569\r
938baa1f 2570 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
93551a01 2571 if (HiiHandles[Index] == HiiHandle) {\r
938baa1f
ED
2572 Find = TRUE;\r
2573 break;\r
2574 }\r
2575 }\r
2576\r
93551a01
ED
2577 FreePool (HiiHandles);\r
2578\r
2579 return Find;\r
2580}\r
2581\r
2582/**\r
2583 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2584\r
2585 @param FormSet The input FormSet which need to validate.\r
2586\r
2587 @retval TRUE The handle is validate.\r
2588 @retval FALSE The handle is invalidate.\r
2589\r
2590**/\r
2591BOOLEAN\r
2592ValidateFormSet (\r
2593 FORM_BROWSER_FORMSET *FormSet\r
2594 )\r
2595{\r
2596 BOOLEAN Find;\r
2597\r
2598 ASSERT (FormSet != NULL);\r
2599\r
2600 Find = ValidateHiiHandle(FormSet->HiiHandle);\r
275ea01e
ED
2601 //\r
2602 // Should not remove the formset which is being used.\r
2603 //\r
2604 if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
0a6f8af5 2605 CleanBrowserStorage(FormSet);\r
938baa1f
ED
2606 RemoveEntryList (&FormSet->Link);\r
2607 DestroyFormSet (FormSet);\r
2608 }\r
2609\r
938baa1f
ED
2610 return Find;\r
2611}\r
7c6c064c
ED
2612/**\r
2613 Check whether need to enable the reset flag in form level.\r
2614 Also clean all ValueChanged flag in question.\r
2615\r
2616 @param SetFlag Whether need to set the Reset Flag.\r
4d4deaac 2617 @param FormSet FormSet data structure.\r
7c6c064c
ED
2618 @param Form Form data structure.\r
2619\r
2620**/\r
2621VOID\r
2622UpdateFlagForForm (\r
2623 IN BOOLEAN SetFlag,\r
4d4deaac 2624 IN FORM_BROWSER_FORMSET *FormSet,\r
7c6c064c
ED
2625 IN FORM_BROWSER_FORM *Form\r
2626 )\r
2627{\r
2628 LIST_ENTRY *Link;\r
2629 FORM_BROWSER_STATEMENT *Question;\r
4d4deaac 2630 BOOLEAN OldValue;\r
7c6c064c 2631\r
7c6c064c
ED
2632 Link = GetFirstNode (&Form->StatementListHead);\r
2633 while (!IsNull (&Form->StatementListHead, Link)) {\r
2634 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4d4deaac 2635 Link = GetNextNode (&Form->StatementListHead, Link);\r
7c6c064c 2636\r
4d4deaac
ED
2637 if (!Question->ValueChanged) {\r
2638 continue;\r
7c6c064c 2639 }\r
4d4deaac
ED
2640\r
2641 OldValue = Question->ValueChanged;\r
2642\r
2643 //\r
2644 // Compare the buffer and editbuffer data to see whether the data has been saved.\r
2645 //\r
2646 Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
2647\r
2648 //\r
2649 // Only the changed data has been saved, then need to set the reset flag.\r
2650 //\r
f2e7732e
ED
2651 if (SetFlag && OldValue && !Question->ValueChanged) {\r
2652 if ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
2653 gResetRequired = TRUE;\r
2654 }\r
2655\r
2656 if ((Question->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
2657 gFlagReconnect = TRUE;\r
2658 }\r
4d4deaac 2659 } \r
7c6c064c
ED
2660 }\r
2661}\r
2662\r
2663/**\r
2664 Check whether need to enable the reset flag.\r
2665 Also clean ValueChanged flag for all statements.\r
2666\r
2667 Form level or formset level, only one.\r
2668 \r
2669 @param SetFlag Whether need to set the Reset Flag.\r
2670 @param FormSet FormSet data structure.\r
2671 @param Form Form data structure.\r
2672\r
2673**/\r
2674VOID\r
2675ValueChangeResetFlagUpdate (\r
2676 IN BOOLEAN SetFlag,\r
2677 IN FORM_BROWSER_FORMSET *FormSet,\r
2678 IN FORM_BROWSER_FORM *Form \r
2679 )\r
2680{\r
2681 FORM_BROWSER_FORM *CurrentForm;\r
2682 LIST_ENTRY *Link;\r
2683\r
7c6c064c 2684 if (Form != NULL) {\r
4d4deaac 2685 UpdateFlagForForm(SetFlag, FormSet, Form);\r
7c6c064c
ED
2686 return;\r
2687 }\r
2688\r
2689 Link = GetFirstNode (&FormSet->FormListHead);\r
2690 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2691 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2692 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2693\r
4d4deaac 2694 UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
7c6c064c
ED
2695 }\r
2696}\r
938baa1f 2697\r
4d4deaac
ED
2698/**\r
2699 Base on the return Progress string to find the form. \r
2700 \r
2701 Base on the first return Offset/Width (Name) string to find the form\r
2702 which keep this string.\r
2703\r
2704 @param FormSet FormSet data structure.\r
2705 @param Storage Storage which has this Progress string.\r
2706 @param Progress The Progress string which has the first fail string.\r
2707 @param RetForm The return form for this progress string.\r
2708 @param RetQuestion The return question for the error progress string.\r
2709\r
2710 @retval TRUE Find the error form and statement for this error progress string.\r
2711 @retval FALSE Not find the error form.\r
2712\r
2713**/\r
2714BOOLEAN\r
2715FindQuestionFromProgress (\r
2716 IN FORM_BROWSER_FORMSET *FormSet,\r
2717 IN BROWSER_STORAGE *Storage,\r
2718 IN EFI_STRING Progress,\r
2719 OUT FORM_BROWSER_FORM **RetForm,\r
2720 OUT FORM_BROWSER_STATEMENT **RetQuestion\r
2721 )\r
2722{\r
2723 LIST_ENTRY *Link;\r
2724 LIST_ENTRY *LinkStorage;\r
2725 LIST_ENTRY *LinkStatement;\r
2726 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2727 FORM_BROWSER_FORM *Form;\r
2728 EFI_STRING EndStr;\r
2729 FORM_BROWSER_STATEMENT *Statement;\r
2730\r
2731 ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
2732\r
2733 ConfigInfo = NULL;\r
2734 *RetForm = NULL;\r
2735 *RetQuestion = NULL;\r
2736\r
2737 //\r
2738 // Skip the first "&" or the ConfigHdr part.\r
2739 //\r
2740 if (*Progress == '&') {\r
2741 Progress++;\r
2742 } else {\r
2743 //\r
2744 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2745 //\r
2746 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2747 //\r
2748 // For Name/Value type, Skip the ConfigHdr part.\r
2749 //\r
2750 EndStr = StrStr (Progress, L"PATH=");\r
e77d2f9d 2751 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2752 while (*EndStr != '&') {\r
2753 EndStr++;\r
2754 }\r
2755\r
2756 *EndStr = '\0';\r
2757 } else {\r
2758 //\r
2759 // For Buffer type, Skip the ConfigHdr part.\r
2760 //\r
2761 EndStr = StrStr (Progress, L"&OFFSET=");\r
e77d2f9d 2762 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2763 *EndStr = '\0';\r
2764 }\r
2765\r
2766 Progress = EndStr + 1;\r
2767 }\r
2768\r
2769 //\r
2770 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2771 //\r
2772 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2773 //\r
2774 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2775 // here, just keep the "Fred" string.\r
2776 //\r
2777 EndStr = StrStr (Progress, L"=");\r
e77d2f9d 2778 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2779 *EndStr = '\0';\r
2780 } else {\r
2781 //\r
2782 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2783 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2784 //\r
2785 EndStr = StrStr (Progress, L"&VALUE=");\r
e77d2f9d 2786 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2787 *EndStr = '\0';\r
2788 }\r
2789\r
2790 //\r
2791 // Search in the form list.\r
2792 //\r
2793 Link = GetFirstNode (&FormSet->FormListHead);\r
2794 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2795 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2796 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2797\r
2798 //\r
2799 // Search in the ConfigReqeust list in this form.\r
2800 //\r
2801 LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
2802 while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
2803 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
2804 LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
2805\r
2806 if (Storage != ConfigInfo->Storage) {\r
2807 continue;\r
2808 }\r
2809\r
2810 if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
2811 //\r
2812 // Find the OffsetWidth string in this form.\r
2813 //\r
2814 *RetForm = Form;\r
2815 break;\r
2816 }\r
2817 }\r
2818\r
2819 if (*RetForm != NULL) {\r
2820 LinkStatement = GetFirstNode (&Form->StatementListHead);\r
2821 while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
2822 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
2823 LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
2824\r
2825 if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
2826 *RetQuestion = Statement;\r
2827 break;\r
2828 }\r
a35ecb75
ED
2829\r
2830 if (Statement->VariableName != NULL && StrStr (Statement->VariableName, Progress) != NULL) {\r
2831 *RetQuestion = Statement;\r
2832 break;\r
2833 }\r
4d4deaac
ED
2834 }\r
2835 }\r
2836\r
2837 if (*RetForm != NULL) {\r
2838 break;\r
2839 }\r
2840 }\r
2841\r
2842 //\r
2843 // restore the OffsetWidth string to the original format.\r
2844 //\r
2845 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2846 *EndStr = '=';\r
2847 } else {\r
2848 *EndStr = '&';\r
2849 }\r
2850\r
5039b444 2851 return (BOOLEAN) (*RetForm != NULL);\r
4d4deaac
ED
2852}\r
2853\r
8066b27e
DB
2854/**\r
2855 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest\r
2856 for form and formset.\r
2857\r
2858 @param Storage Storage which has this Progress string.\r
2859 @param ConfigRequest The ConfigRequest string.\r
2860 @param Progress The Progress string which has the first fail string.\r
2861 @param RestoreConfigRequest Return the RestoreConfigRequest string.\r
2862 @param SyncConfigRequest Return the SyncConfigRequest string.\r
2863\r
2864**/\r
2865VOID\r
2866GetSyncRestoreConfigRequest(\r
2867 IN BROWSER_STORAGE *Storage,\r
2868 IN EFI_STRING ConfigRequest,\r
2869 IN EFI_STRING Progress,\r
2870 OUT EFI_STRING *RestoreConfigRequest,\r
2871 OUT EFI_STRING *SyncConfigRequest\r
2872 )\r
2873{\r
2874 EFI_STRING EndStr;\r
2875 EFI_STRING ConfigHdrEndStr;\r
2876 EFI_STRING ElementStr;\r
2877 UINTN TotalSize;\r
2878 UINTN RestoreEleSize;\r
2879 UINTN SyncSize;\r
2880\r
2881 ASSERT ((*Progress == L'&') || (*Progress == L'G'));\r
2882 //\r
2883 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.\r
2884 // Need to restore all the fields in the ConfigRequest.\r
2885 //\r
2886 if (*Progress == L'G') {\r
2887 *RestoreConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
2888 ASSERT (*RestoreConfigRequest != NULL);\r
2889 return;\r
2890 }\r
2891\r
2892 //\r
2893 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2894 //\r
2895 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2896 //\r
2897 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2898 // here, just keep the "Fred" string.\r
2899 //\r
2900 EndStr = StrStr (Progress, L"=");\r
2901 ASSERT (EndStr != NULL);\r
2902 *EndStr = L'\0';\r
2903 //\r
2904 // Find the ConfigHdr in ConfigRequest.\r
2905 //\r
2906 ConfigHdrEndStr = StrStr (ConfigRequest, L"PATH=");\r
2907 ASSERT (ConfigHdrEndStr != NULL);\r
2908 while (*ConfigHdrEndStr != L'&') {\r
2909 ConfigHdrEndStr++;\r
2910 }\r
2911 } else {\r
2912 //\r
2913 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2914 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2915 //\r
2916 EndStr = StrStr (Progress, L"&VALUE=");\r
2917 ASSERT (EndStr != NULL);\r
2918 *EndStr = L'\0';\r
2919 //\r
2920 // Find the ConfigHdr in ConfigRequest.\r
2921 //\r
2922 ConfigHdrEndStr = StrStr (ConfigRequest, L"&OFFSET=");\r
2923 }\r
2924 //\r
2925 // Find the first fail pair in the ConfigRequest.\r
2926 //\r
2927 ElementStr = StrStr (ConfigRequest, Progress);\r
2928 ASSERT (ElementStr != NULL);\r
2929 //\r
2930 // To get the RestoreConfigRequest.\r
2931 //\r
2932 RestoreEleSize = StrSize (ElementStr);\r
2933 TotalSize = (ConfigHdrEndStr - ConfigRequest) * sizeof (CHAR16) + RestoreEleSize + sizeof (CHAR16);\r
2934 *RestoreConfigRequest = AllocateZeroPool (TotalSize);\r
2935 ASSERT (*RestoreConfigRequest != NULL);\r
2936 StrnCpyS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ConfigRequest, ConfigHdrEndStr - ConfigRequest);\r
2937 StrCatS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ElementStr);\r
2938 //\r
2939 // To get the SyncConfigRequest.\r
2940 //\r
2941 SyncSize = StrSize (ConfigRequest) - RestoreEleSize + sizeof (CHAR16);\r
2942 *SyncConfigRequest = AllocateZeroPool (SyncSize);\r
2943 ASSERT (*SyncConfigRequest != NULL);\r
2944 StrnCpyS (*SyncConfigRequest, SyncSize / sizeof (CHAR16), ConfigRequest, SyncSize / sizeof (CHAR16) - 1);\r
2945\r
2946 //\r
2947 // restore the Progress string to the original format.\r
2948 //\r
2949 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2950 *EndStr = L'=';\r
2951 } else {\r
2952 *EndStr = L'&';\r
2953 }\r
2954}\r
2955\r
4d4deaac
ED
2956/**\r
2957 Popup an save error info and get user input.\r
2958\r
2959 @param TitleId The form title id.\r
2960 @param HiiHandle The hii handle for this package.\r
2961\r
2962 @retval UINT32 The user select option for the save fail.\r
2963 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2964**/\r
2965UINT32\r
2966ConfirmSaveFail (\r
2967 IN EFI_STRING_ID TitleId,\r
2968 IN EFI_HII_HANDLE HiiHandle\r
2969 )\r
2970{\r
2971 CHAR16 *FormTitle;\r
2972 CHAR16 *StringBuffer;\r
2973 UINT32 RetVal;\r
2974\r
2975 FormTitle = GetToken (TitleId, HiiHandle);\r
2976\r
2977 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2978 ASSERT (StringBuffer != NULL);\r
2979\r
2980 UnicodeSPrint (\r
2981 StringBuffer, \r
2982 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2983 L"Submit Fail For Form: %s.", \r
2984 FormTitle\r
2985 );\r
2986\r
2987 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
2988\r
2989 FreePool (StringBuffer);\r
2990 FreePool (FormTitle);\r
2991\r
2992 return RetVal;\r
2993}\r
2994\r
2995/**\r
2996 Popup an NO_SUBMIT_IF error info and get user input.\r
2997\r
2998 @param TitleId The form title id.\r
2999 @param HiiHandle The hii handle for this package.\r
3000\r
3001 @retval UINT32 The user select option for the save fail.\r
3002 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
3003**/\r
3004UINT32\r
3005ConfirmNoSubmitFail (\r
3006 IN EFI_STRING_ID TitleId,\r
3007 IN EFI_HII_HANDLE HiiHandle\r
3008 )\r
3009{\r
3010 CHAR16 *FormTitle;\r
3011 CHAR16 *StringBuffer;\r
3012 UINT32 RetVal;\r
3013\r
3014 FormTitle = GetToken (TitleId, HiiHandle);\r
3015\r
3016 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
3017 ASSERT (StringBuffer != NULL);\r
3018\r
3019 UnicodeSPrint (\r
3020 StringBuffer, \r
3021 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
3022 L"NO_SUBMIT_IF error For Form: %s.", \r
3023 FormTitle\r
3024 );\r
3025\r
3026 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
3027\r
3028 FreePool (StringBuffer);\r
3029 FreePool (FormTitle);\r
3030\r
3031 return RetVal;\r
3032}\r
3033\r
b18e7050 3034/**\r
48a9d5f7 3035 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 3036\r
3037 @param FormSet FormSet data structure.\r
3038 @param Form Form data structure.\r
48a9d5f7 3039 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
3040\r
3041 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3042 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
3043\r
3044**/\r
3045EFI_STATUS\r
3046DiscardForm (\r
3047 IN FORM_BROWSER_FORMSET *FormSet,\r
3048 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 3049 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
3050 )\r
3051{\r
48a9d5f7
LG
3052 LIST_ENTRY *Link;\r
3053 FORMSET_STORAGE *Storage;\r
b18e7050 3054 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
6e74560f
ED
3055 FORM_BROWSER_FORMSET *LocalFormSet;\r
3056 FORM_BROWSER_FORMSET *OldFormSet;\r
b18e7050 3057\r
48a9d5f7
LG
3058 //\r
3059 // Check the supported setting level.\r
3060 //\r
3061 if (SettingScope >= MaxLevel) {\r
3062 return EFI_UNSUPPORTED;\r
3063 }\r
b18e7050 3064\r
7c6c064c 3065 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
48a9d5f7
LG
3066 ConfigInfo = NULL;\r
3067 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3068 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3069 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3070 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 3071\r
48a9d5f7
LG
3072 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3073 continue;\r
3074 }\r
3075\r
3076 //\r
3077 // Skip if there is no RequestElement\r
3078 //\r
3079 if (ConfigInfo->ElementCount == 0) {\r
3080 continue;\r
b18e7050
ED
3081 }\r
3082\r
48a9d5f7
LG
3083 //\r
3084 // Prepare <ConfigResp>\r
3085 //\r
4d4deaac 3086 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
816a7110 3087\r
816a7110
ED
3088 //\r
3089 // Call callback with Changed type to inform the driver.\r
3090 //\r
3091 SendDiscardInfoToDriver (FormSet, Form);\r
3092 }\r
3093\r
4d4deaac 3094 ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
7c6c064c 3095 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
f1660263 3096\r
48a9d5f7
LG
3097 //\r
3098 // Discard Buffer storage or Name/Value storage\r
3099 //\r
3100 Link = GetFirstNode (&FormSet->StorageListHead);\r
3101 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3102 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3103 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3104\r
94f3aae7 3105 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
48a9d5f7
LG
3106 continue;\r
3107 }\r
3108\r
b18e7050 3109 //\r
48a9d5f7 3110 // Skip if there is no RequestElement\r
b18e7050 3111 //\r
48a9d5f7
LG
3112 if (Storage->ElementCount == 0) {\r
3113 continue;\r
3114 }\r
b18e7050 3115\r
4d4deaac 3116 SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
48a9d5f7 3117 }\r
f1660263
ED
3118\r
3119 Link = GetFirstNode (&FormSet->FormListHead);\r
3120 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3121 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3122 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3123 \r
3124 //\r
3125 // Call callback with Changed type to inform the driver.\r
3126 //\r
3127 SendDiscardInfoToDriver (FormSet, Form);\r
3128 }\r
b18e7050 3129\r
7c6c064c 3130 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
48a9d5f7
LG
3131 } else if (SettingScope == SystemLevel) {\r
3132 //\r
3133 // System Level Discard.\r
3134 //\r
6e74560f
ED
3135 OldFormSet = mSystemLevelFormSet;\r
3136\r
48a9d5f7
LG
3137 //\r
3138 // Discard changed value for each FormSet in the maintain list.\r
3139 //\r
3140 Link = GetFirstNode (&gBrowserFormSetList);\r
3141 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3142 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 3143 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
3144 if (!ValidateFormSet(LocalFormSet)) {\r
3145 continue;\r
3146 }\r
6e74560f
ED
3147\r
3148 mSystemLevelFormSet = LocalFormSet;\r
3149\r
938baa1f 3150 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7 3151 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 3152 //\r
48a9d5f7 3153 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 3154 //\r
0a6f8af5 3155 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
3156 RemoveEntryList (&LocalFormSet->Link);\r
3157 DestroyFormSet (LocalFormSet);\r
b18e7050 3158 }\r
b18e7050 3159 }\r
6e74560f
ED
3160\r
3161 mSystemLevelFormSet = OldFormSet;\r
b18e7050
ED
3162 }\r
3163\r
3164 return EFI_SUCCESS; \r
3165}\r
3166\r
3167/**\r
4d4deaac 3168 Submit data for a form.\r
b18e7050
ED
3169\r
3170 @param FormSet FormSet data structure.\r
3171 @param Form Form data structure.\r
7936fb6a 3172\r
3173 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3174 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 3175\r
3176**/\r
3177EFI_STATUS\r
4d4deaac 3178SubmitForForm (\r
7936fb6a 3179 IN FORM_BROWSER_FORMSET *FormSet,\r
4d4deaac 3180 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3181 )\r
3182{\r
3183 EFI_STATUS Status;\r
3184 LIST_ENTRY *Link;\r
3185 EFI_STRING ConfigResp;\r
3186 EFI_STRING Progress;\r
94f3aae7 3187 BROWSER_STORAGE *Storage;\r
b18e7050 3188 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
fdd530d6
DB
3189 BOOLEAN SubmitFormFail;\r
3190\r
3191 SubmitFormFail = FALSE;\r
7936fb6a 3192\r
4d4deaac
ED
3193 if (!IsNvUpdateRequiredForForm (Form)) {\r
3194 return EFI_SUCCESS;\r
3195 }\r
3196\r
3197 Status = NoSubmitCheck (FormSet, &Form, NULL);\r
3198 if (EFI_ERROR (Status)) {\r
3199 return Status;\r
3200 }\r
3201\r
3202 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3203 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3204 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3205 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
3206\r
3207 Storage = ConfigInfo->Storage;\r
3208 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3209 continue;\r
3210 }\r
3211\r
3212 //\r
3213 // Skip if there is no RequestElement\r
3214 //\r
3215 if (ConfigInfo->ElementCount == 0) {\r
3216 continue;\r
3217 }\r
3218\r
3219 //\r
3220 // 1. Prepare <ConfigResp>\r
3221 //\r
3222 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
3223 if (EFI_ERROR (Status)) {\r
3224 return Status;\r
3225 }\r
3226\r
3227 //\r
3228 // 2. Set value to hii config routine protocol.\r
3229 //\r
3230 Status = mHiiConfigRouting->RouteConfig (\r
3231 mHiiConfigRouting,\r
3232 ConfigResp,\r
3233 &Progress\r
3234 );\r
4d4deaac
ED
3235\r
3236 if (EFI_ERROR (Status)) {\r
8066b27e
DB
3237 //\r
3238 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
3239 //\r
fdd530d6 3240 SubmitFormFail = TRUE;\r
8066b27e 3241 GetSyncRestoreConfigRequest (ConfigInfo->Storage, ConfigInfo->ConfigRequest, Progress, &ConfigInfo->RestoreConfigRequest, &ConfigInfo->SyncConfigRequest);\r
4d4deaac 3242 InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
fa209e8c 3243 FreePool (ConfigResp);\r
4d4deaac
ED
3244 continue;\r
3245 }\r
3246\r
fa209e8c 3247 FreePool (ConfigResp);\r
4d4deaac
ED
3248 //\r
3249 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
3250 //\r
3251 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
3252 }\r
3253\r
48a9d5f7 3254 //\r
4d4deaac 3255 // 4. Process the save failed storage.\r
48a9d5f7 3256 //\r
4d4deaac
ED
3257 if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3258 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3259 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3260 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3261 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3262 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
8066b27e
DB
3263 //\r
3264 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3265 // base on the SyncConfigRequest to Sync the buffer.\r
3266 //\r
3267 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->RestoreConfigRequest, FALSE);\r
3268 FreePool (ConfigInfo->RestoreConfigRequest);\r
3269 ConfigInfo->RestoreConfigRequest = NULL;\r
3270 if (ConfigInfo->SyncConfigRequest != NULL) {\r
3271 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->SyncConfigRequest, TRUE);\r
3272 FreePool (ConfigInfo->SyncConfigRequest);\r
3273 ConfigInfo->SyncConfigRequest = NULL;\r
3274 }\r
4d4deaac
ED
3275\r
3276 Status = EFI_SUCCESS;\r
3277 }\r
3278 } else {\r
3279 Status = EFI_UNSUPPORTED;\r
3280 }\r
3281\r
3282 //\r
3283 // Free Form save fail list.\r
3284 //\r
3285 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3286 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3287 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3288 RemoveEntryList (&ConfigInfo->SaveFailLink);\r
3289 }\r
48a9d5f7
LG
3290 }\r
3291\r
7936fb6a 3292 //\r
4d4deaac 3293 // 5. Update the NV flag.\r
7936fb6a 3294 //\r
4d4deaac
ED
3295 ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
3296\r
3cb44c20
DB
3297 //\r
3298 // 6 Call callback with Submitted type to inform the driver.\r
3299 //\r
fdd530d6
DB
3300 if (!SubmitFormFail) {\r
3301 SubmitCallback (FormSet, Form);\r
3302 }\r
3cb44c20 3303\r
4d4deaac
ED
3304 return Status;\r
3305}\r
3306\r
3307/**\r
3308 Submit data for a formset.\r
3309\r
3310 @param FormSet FormSet data structure.\r
3311 @param SkipProcessFail Whether skip to process the save failed storage.\r
3312 If submit formset is called when do system level save, \r
3313 set this value to true and process the failed formset \r
3314 together. \r
3315 if submit formset is called when do formset level save,\r
3316 set the value to false and process the failed storage\r
3317 right after process all storages for this formset.\r
3318\r
3319 @retval EFI_SUCCESS The function completed successfully.\r
3320 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3321\r
3322**/\r
3323EFI_STATUS\r
3324SubmitForFormSet (\r
3325 IN FORM_BROWSER_FORMSET *FormSet,\r
3326 IN BOOLEAN SkipProcessFail\r
3327 )\r
3328{\r
3329 EFI_STATUS Status;\r
3330 LIST_ENTRY *Link;\r
3331 EFI_STRING ConfigResp;\r
3332 EFI_STRING Progress;\r
3333 BROWSER_STORAGE *Storage;\r
3334 FORMSET_STORAGE *FormSetStorage;\r
3335 FORM_BROWSER_FORM *Form;\r
3336 BOOLEAN HasInserted;\r
3337 FORM_BROWSER_STATEMENT *Question;\r
fdd530d6 3338 BOOLEAN SubmitFormSetFail;\r
4d4deaac
ED
3339\r
3340 HasInserted = FALSE;\r
fdd530d6 3341 SubmitFormSetFail = FALSE;\r
4d4deaac
ED
3342\r
3343 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
3344 return EFI_SUCCESS;\r
b18e7050 3345 }\r
4d4deaac
ED
3346\r
3347 Form = NULL; \r
3348 Status = NoSubmitCheck (FormSet, &Form, &Question);\r
7936fb6a 3349 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
3350 if (SkipProcessFail) {\r
3351 //\r
3352 // Process NO_SUBMIT check first, so insert it at head.\r
3353 //\r
3354 FormSet->SaveFailForm = Form;\r
3355 FormSet->SaveFailStatement = Question;\r
3356 InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3357 }\r
3358\r
7936fb6a 3359 return Status;\r
3360 }\r
3361\r
4d4deaac
ED
3362 Form = NULL;\r
3363 Question = NULL;\r
3364 //\r
3365 // Submit Buffer storage or Name/Value storage\r
3366 //\r
3367 Link = GetFirstNode (&FormSet->StorageListHead);\r
3368 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3369 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3370 Storage = FormSetStorage->BrowserStorage;\r
3371 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
7936fb6a 3372\r
4d4deaac
ED
3373 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3374 continue;\r
3375 }\r
7936fb6a 3376\r
4d4deaac
ED
3377 //\r
3378 // Skip if there is no RequestElement\r
3379 //\r
3380 if (FormSetStorage->ElementCount == 0) {\r
3381 continue;\r
3382 }\r
7936fb6a 3383\r
4d4deaac
ED
3384 //\r
3385 // 1. Prepare <ConfigResp>\r
3386 //\r
3387 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
3388 if (EFI_ERROR (Status)) {\r
3389 return Status;\r
3390 }\r
b18e7050 3391\r
4d4deaac
ED
3392 //\r
3393 // 2. Send <ConfigResp> to Routine config Protocol.\r
3394 //\r
3395 Status = mHiiConfigRouting->RouteConfig (\r
3396 mHiiConfigRouting,\r
3397 ConfigResp,\r
3398 &Progress\r
3399 );\r
3400 if (EFI_ERROR (Status)) {\r
8066b27e
DB
3401 //\r
3402 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
3403 //\r
fdd530d6 3404 SubmitFormSetFail = TRUE;\r
8066b27e 3405 GetSyncRestoreConfigRequest (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, Progress, &FormSetStorage->RestoreConfigRequest, &FormSetStorage->SyncConfigRequest);\r
4d4deaac
ED
3406 InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
3407 if (!HasInserted) {\r
3408 //\r
3409 // Call submit formset for system level, save the formset info\r
3410 // and process later.\r
3411 //\r
3412 FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
3413 ASSERT (Form != NULL && Question != NULL);\r
3414 FormSet->SaveFailForm = Form;\r
3415 FormSet->SaveFailStatement = Question;\r
3416 if (SkipProcessFail) {\r
3417 InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3418 }\r
3419 HasInserted = TRUE;\r
b18e7050 3420 }\r
7248790e 3421\r
b18e7050 3422 FreePool (ConfigResp);\r
4d4deaac 3423 continue;\r
7936fb6a 3424 }\r
3425\r
4d4deaac 3426 FreePool (ConfigResp);\r
cce6230f 3427 //\r
4d4deaac 3428 // 3. Config success, update storage shadow Buffer\r
7936fb6a 3429 //\r
4d4deaac
ED
3430 SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
3431 }\r
b18e7050 3432\r
4d4deaac
ED
3433 //\r
3434 // 4. Has save fail storage need to handle.\r
3435 //\r
3436 if (Form != NULL) {\r
3437 if (!SkipProcessFail) {\r
b18e7050 3438 //\r
4d4deaac 3439 // If not in system level, just handl the save failed storage here.\r
b18e7050 3440 //\r
4d4deaac
ED
3441 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3442 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3443 while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
3444 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3445 Storage = FormSetStorage->BrowserStorage;\r
3446 Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
8066b27e
DB
3447 //\r
3448 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3449 // base on the SyncConfigRequest to Sync the buffer.\r
3450 //\r
3451 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
3452 FreePool (FormSetStorage->RestoreConfigRequest);\r
3453 FormSetStorage->RestoreConfigRequest = NULL;\r
3454 if (FormSetStorage->SyncConfigRequest != NULL) {\r
3455 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
3456 FreePool (FormSetStorage->SyncConfigRequest);\r
3457 FormSetStorage->SyncConfigRequest = NULL;\r
3458 }\r
4d4deaac
ED
3459\r
3460 Status = EFI_SUCCESS;\r
3461 }\r
3462 } else {\r
3463 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3464\r
3465 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3466 gCurrentSelection->Handle = FormSet->HiiHandle;\r
3467 CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
3468 gCurrentSelection->FormId = Form->FormId;\r
3469 gCurrentSelection->QuestionId = Question->QuestionId;\r
3470\r
3471 Status = EFI_UNSUPPORTED;\r
7936fb6a 3472 }\r
b18e7050 3473\r
7248790e 3474 //\r
4d4deaac 3475 // Free FormSet save fail list.\r
7248790e 3476 //\r
4d4deaac
ED
3477 while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
3478 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3479 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3480 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
b18e7050 3481 }\r
4d4deaac 3482 } else {\r
b18e7050 3483 //\r
4d4deaac 3484 // If in system level, just return error and handle the failed formset later.\r
b18e7050 3485 //\r
4d4deaac
ED
3486 Status = EFI_UNSUPPORTED;\r
3487 }\r
3488 }\r
3489\r
3490 //\r
3491 // 5. Update the NV flag.\r
3492 // \r
3493 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
3494\r
3cb44c20
DB
3495 //\r
3496 // 6. Call callback with Submitted type to inform the driver.\r
3497 //\r
fdd530d6
DB
3498 if (!SubmitFormSetFail) {\r
3499 SubmitCallback (FormSet, NULL);\r
3500 }\r
3cb44c20 3501\r
4d4deaac
ED
3502 return Status;\r
3503}\r
3504\r
3505/**\r
3506 Submit data for all formsets.\r
3507\r
3508 @retval EFI_SUCCESS The function completed successfully.\r
3509 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3510\r
3511**/\r
3512EFI_STATUS\r
3513SubmitForSystem (\r
3514 VOID\r
3515 )\r
3516{\r
3517 EFI_STATUS Status;\r
3518 LIST_ENTRY *Link;\r
3519 LIST_ENTRY *StorageLink;\r
4d4deaac
ED
3520 FORMSET_STORAGE *FormSetStorage;\r
3521 FORM_BROWSER_FORM *Form;\r
3522 FORM_BROWSER_FORMSET *LocalFormSet;\r
3523 UINT32 UserSelection;\r
3524 FORM_BROWSER_STATEMENT *Question;\r
3525\r
3526 mSystemSubmit = TRUE;\r
3527 Link = GetFirstNode (&gBrowserFormSetList);\r
3528 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3529 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3530 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3531 if (!ValidateFormSet(LocalFormSet)) {\r
3532 continue;\r
3533 }\r
3534\r
3535 Status = SubmitForFormSet (LocalFormSet, TRUE);\r
3536 if (EFI_ERROR (Status)) {\r
3537 continue;\r
7936fb6a 3538 }\r
7936fb6a 3539\r
cce6230f 3540 //\r
4d4deaac
ED
3541 // Remove maintain backup list after save except for the current using FormSet.\r
3542 // \r
3543 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3544 CleanBrowserStorage(LocalFormSet);\r
3545 RemoveEntryList (&LocalFormSet->Link);\r
3546 DestroyFormSet (LocalFormSet);\r
3547 }\r
3548 }\r
3549 mSystemSubmit = FALSE;\r
3550\r
3551 Status = EFI_SUCCESS;\r
3552\r
3553 //\r
3554 // Process the save failed formsets.\r
3555 //\r
3556 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3557 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3558 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3559 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3560\r
3561 if (!ValidateFormSet(LocalFormSet)) {\r
3562 continue;\r
3563 }\r
3564\r
3565 Form = LocalFormSet->SaveFailForm;\r
3566 Question= LocalFormSet->SaveFailStatement;\r
48a9d5f7
LG
3567\r
3568 //\r
4d4deaac 3569 // Confirm with user, get user input.\r
48a9d5f7 3570 //\r
4d4deaac
ED
3571 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3572 //\r
3573 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
3574 //\r
3575 UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3576 } else {\r
3577 UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3578 }\r
3579\r
3580 if (UserSelection == BROWSER_ACTION_DISCARD) {\r
3581 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3582 StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
3583 while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
3584 FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
4d4deaac
ED
3585 StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
3586\r
3587 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3588 }\r
3589 } else {\r
3590 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3591 while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
3592 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
4d4deaac 3593 StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
8066b27e
DB
3594 //\r
3595 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3596 // base on the SyncConfigRequest to Sync the buffer.\r
3597 //\r
3598 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
3599 FreePool (FormSetStorage->RestoreConfigRequest);\r
3600 FormSetStorage->RestoreConfigRequest = NULL;\r
3601 if ( FormSetStorage->SyncConfigRequest != NULL) {\r
3602 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
3603 FreePool (FormSetStorage->SyncConfigRequest);\r
3604 FormSetStorage->SyncConfigRequest = NULL;\r
3605 }\r
4d4deaac 3606 }\r
938baa1f 3607 }\r
4d4deaac 3608\r
48a9d5f7 3609 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
0a6f8af5 3610 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7 3611 RemoveEntryList (&LocalFormSet->Link);\r
4d4deaac 3612 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
48a9d5f7 3613 DestroyFormSet (LocalFormSet);\r
4d4deaac
ED
3614 } else {\r
3615 ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
48a9d5f7 3616 }\r
4d4deaac
ED
3617 } else {\r
3618 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3619 NoSubmitCheck (LocalFormSet, &Form, &Question);\r
3620 }\r
3621\r
3622 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3623\r
3624 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3625 gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
3626 CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
3627 gCurrentSelection->FormId = Form->FormId;\r
3628 gCurrentSelection->QuestionId = Question->QuestionId;\r
3629\r
3630 Status = EFI_UNSUPPORTED;\r
3631 break;\r
48a9d5f7 3632 }\r
7936fb6a 3633 }\r
3634\r
4d4deaac
ED
3635 //\r
3636 // Clean the list which will not process.\r
3637 //\r
3638 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3639 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3640 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3641 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3642\r
3643 while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3644 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3645 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3646 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3647 }\r
3648 }\r
3649\r
3650 return Status;\r
3651}\r
3652\r
3653/**\r
3654 Submit data based on the input Setting level (Form, FormSet or System).\r
3655\r
3656 @param FormSet FormSet data structure.\r
3657 @param Form Form data structure.\r
3658 @param SettingScope Setting Scope for Submit action.\r
3659\r
3660 @retval EFI_SUCCESS The function completed successfully.\r
3661 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3662\r
3663**/\r
3664EFI_STATUS\r
3665SubmitForm (\r
3666 IN FORM_BROWSER_FORMSET *FormSet,\r
3667 IN FORM_BROWSER_FORM *Form,\r
3668 IN BROWSER_SETTING_SCOPE SettingScope\r
3669 )\r
3670{\r
3671 EFI_STATUS Status;\r
3672\r
3673 switch (SettingScope) {\r
3674 case FormLevel:\r
3675 Status = SubmitForForm(FormSet, Form);\r
3676 break;\r
3677\r
3678 case FormSetLevel:\r
3679 Status = SubmitForFormSet (FormSet, FALSE);\r
3680 break;\r
3681\r
3682 case SystemLevel:\r
3683 Status = SubmitForSystem ();\r
3684 break;\r
3685\r
3686 default:\r
3687 Status = EFI_UNSUPPORTED;\r
3688 break;\r
3689 }\r
3690\r
3691 return Status;\r
7936fb6a 3692}\r
3693\r
ee31d1be 3694/**\r
7a9612ce
ED
3695 Converts the unicode character of the string from uppercase to lowercase.\r
3696 This is a internal function.\r
ee31d1be 3697\r
7a9612ce 3698 @param ConfigString String to be converted\r
ee31d1be
ED
3699\r
3700**/\r
7a9612ce
ED
3701VOID\r
3702EFIAPI\r
3703HiiToLower (\r
3704 IN EFI_STRING ConfigString\r
ee31d1be
ED
3705 )\r
3706{\r
7a9612ce
ED
3707 EFI_STRING String;\r
3708 BOOLEAN Lower;\r
ee31d1be 3709\r
7a9612ce 3710 ASSERT (ConfigString != NULL);\r
ee31d1be
ED
3711\r
3712 //\r
7a9612ce 3713 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
ee31d1be 3714 //\r
7a9612ce
ED
3715 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
3716 if (*String == L'=') {\r
3717 Lower = TRUE;\r
3718 } else if (*String == L'&') {\r
3719 Lower = FALSE;\r
3720 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
3721 *String = (CHAR16) (*String - L'A' + L'a');\r
3722 }\r
ee31d1be 3723 }\r
7a9612ce 3724}\r
ee31d1be 3725\r
7a9612ce
ED
3726/**\r
3727 Find the point in the ConfigResp string for this question.\r
3728\r
3729 @param Question The question.\r
3730 @param ConfigResp Get ConfigResp string.\r
3731\r
3732 @retval point to the offset where is for this question.\r
3733\r
3734**/\r
3735CHAR16 *\r
3736GetOffsetFromConfigResp (\r
3737 IN FORM_BROWSER_STATEMENT *Question,\r
3738 IN CHAR16 *ConfigResp\r
3739 )\r
3740{\r
3741 CHAR16 *RequestElement;\r
3742 CHAR16 *BlockData;\r
ee31d1be
ED
3743\r
3744 //\r
7a9612ce 3745 // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
ee31d1be 3746 //\r
7a9612ce
ED
3747 if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3748 RequestElement = StrStr (ConfigResp, Question->VariableName);\r
3749 if (RequestElement != NULL) {\r
3750 //\r
3751 // Skip the "VariableName=" field.\r
3752 //\r
3753 RequestElement += StrLen (Question->VariableName) + 1;\r
3754 }\r
ee31d1be 3755\r
7a9612ce 3756 return RequestElement;\r
ee31d1be
ED
3757 }\r
3758\r
3759 //\r
7a9612ce 3760 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
ee31d1be 3761 //\r
7a9612ce 3762\r
f3587039
DB
3763 //\r
3764 // Convert all hex digits in ConfigResp to lower case before searching.\r
3765 //\r
3766 HiiToLower (ConfigResp);\r
3767\r
ee31d1be 3768 //\r
7a9612ce 3769 // 1. Directly use Question->BlockName to find.\r
ee31d1be 3770 //\r
7a9612ce
ED
3771 RequestElement = StrStr (ConfigResp, Question->BlockName);\r
3772 if (RequestElement != NULL) {\r
3773 //\r
3774 // Skip the "Question->BlockName&VALUE=" field.\r
3775 //\r
3776 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
3777 return RequestElement;\r
7248790e 3778 }\r
7a9612ce 3779 \r
ee31d1be 3780 //\r
7a9612ce 3781 // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
ee31d1be 3782 //\r
7a9612ce
ED
3783 BlockData = AllocateCopyPool (StrSize(Question->BlockName), Question->BlockName);\r
3784 ASSERT (BlockData != NULL);\r
3785 HiiToLower (BlockData);\r
3786 RequestElement = StrStr (ConfigResp, BlockData);\r
3787 FreePool (BlockData);\r
3788\r
3789 if (RequestElement != NULL) {\r
ee31d1be 3790 //\r
7a9612ce 3791 // Skip the "Question->BlockName&VALUE=" field.\r
ee31d1be 3792 //\r
7a9612ce 3793 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
ee31d1be 3794 }\r
7a9612ce
ED
3795\r
3796 return RequestElement;\r
3797}\r
3798\r
3799/**\r
3800 Get Question default value from AltCfg string.\r
3801\r
3802 @param FormSet The form set.\r
3803 @param Form The form\r
3804 @param Question The question.\r
3805\r
3806 @retval EFI_SUCCESS Question is reset to default value.\r
3807\r
3808**/\r
3809EFI_STATUS\r
3810GetDefaultValueFromAltCfg (\r
3811 IN FORM_BROWSER_FORMSET *FormSet,\r
3812 IN FORM_BROWSER_FORM *Form,\r
3813 IN OUT FORM_BROWSER_STATEMENT *Question\r
3814 )\r
3815{ \r
3816 BROWSER_STORAGE *Storage;\r
3817 FORMSET_STORAGE *FormSetStorage;\r
3818 CHAR16 *ConfigResp;\r
3819 CHAR16 *Value;\r
3820 LIST_ENTRY *Link;\r
3821 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
3822\r
3823 Storage = Question->Storage;\r
3824 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3825 return EFI_NOT_FOUND;\r
ee31d1be 3826 }\r
ee31d1be
ED
3827\r
3828 //\r
7a9612ce
ED
3829 // Try to get AltCfg string from form. If not found it, then\r
3830 // try to get it from formset.\r
ee31d1be 3831 //\r
7a9612ce
ED
3832 ConfigResp = NULL;\r
3833 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3834 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3835 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3836 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
ee31d1be 3837\r
7a9612ce
ED
3838 if (Storage == ConfigInfo->Storage) {\r
3839 ConfigResp = ConfigInfo->ConfigAltResp;\r
3840 break;\r
ee31d1be 3841 }\r
7a9612ce
ED
3842 }\r
3843\r
3844 if (ConfigResp == NULL) {\r
3845 Link = GetFirstNode (&FormSet->StorageListHead);\r
3846 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3847 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3848 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3849\r
3850 if (Storage == FormSetStorage->BrowserStorage) {\r
3851 ConfigResp = FormSetStorage->ConfigAltResp;\r
3852 break;\r
25361615
ED
3853 }\r
3854 }\r
3855 }\r
b9feb4bd 3856\r
7a9612ce
ED
3857 if (ConfigResp == NULL) {\r
3858 return EFI_NOT_FOUND;\r
7c6c064c
ED
3859 }\r
3860\r
7a9612ce
ED
3861 Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
3862 if (Value == NULL) {\r
3863 return EFI_NOT_FOUND;\r
7c6c064c
ED
3864 }\r
3865\r
7a9612ce 3866 return BufferToValue (Question, Value);\r
7c6c064c
ED
3867}\r
3868\r
3869/**\r
3870 Get default Id value used for browser.\r
3871\r
3872 @param DefaultId The default id value used by hii.\r
3873\r
3874 @retval Browser used default value.\r
3875\r
3876**/\r
3877INTN\r
3878GetDefaultIdForCallBack (\r
3879 UINTN DefaultId\r
3880 )\r
3881{ \r
3882 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3883 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
3884 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3885 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
3886 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
3887 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
3888 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
3889 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
3890 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
3891 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
3892 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
3893 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
3894 } else {\r
3895 return -1;\r
3896 }\r
3897}\r
3898\r
3899\r
3900\r
3901/**\r
3902 Return data element in an Array by its Index.\r
3903\r
3904 @param Array The data array.\r
3905 @param Type Type of the data in this array.\r
3906 @param Index Zero based index for data in this array.\r
3907\r
3908 @retval Value The data to be returned\r
3909\r
3910**/\r
3911UINT64\r
3912GetArrayData (\r
3913 IN VOID *Array,\r
3914 IN UINT8 Type,\r
3915 IN UINTN Index\r
3916 )\r
3917{\r
3918 UINT64 Data;\r
3919\r
3920 ASSERT (Array != NULL);\r
3921\r
3922 Data = 0;\r
3923 switch (Type) {\r
3924 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3925 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
3926 break;\r
3927\r
3928 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3929 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
3930 break;\r
3931\r
3932 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3933 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
3934 break;\r
3935\r
3936 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3937 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
3938 break;\r
3939\r
3940 default:\r
3941 break;\r
3942 }\r
3943\r
3944 return Data;\r
3945}\r
3946\r
3947\r
3948/**\r
3949 Set value of a data element in an Array by its Index.\r
3950\r
3951 @param Array The data array.\r
3952 @param Type Type of the data in this array.\r
3953 @param Index Zero based index for data in this array.\r
3954 @param Value The value to be set.\r
3955\r
3956**/\r
3957VOID\r
3958SetArrayData (\r
3959 IN VOID *Array,\r
3960 IN UINT8 Type,\r
3961 IN UINTN Index,\r
3962 IN UINT64 Value\r
3963 )\r
3964{\r
3965\r
3966 ASSERT (Array != NULL);\r
b9feb4bd 3967\r
7c6c064c
ED
3968 switch (Type) {\r
3969 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3970 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
3971 break;\r
25361615 3972\r
7c6c064c
ED
3973 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3974 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
3975 break;\r
3976\r
3977 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3978 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
3979 break;\r
3980\r
3981 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3982 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
3983 break;\r
3984\r
3985 default:\r
3986 break;\r
3987 }\r
ee31d1be
ED
3988}\r
3989\r
3990/**\r
7c6c064c 3991 Search an Option of a Question by its value.\r
ee31d1be 3992\r
7c6c064c
ED
3993 @param Question The Question\r
3994 @param OptionValue Value for Option to be searched.\r
ee31d1be 3995\r
7c6c064c
ED
3996 @retval Pointer Pointer to the found Option.\r
3997 @retval NULL Option not found.\r
ee31d1be
ED
3998\r
3999**/\r
7c6c064c
ED
4000QUESTION_OPTION *\r
4001ValueToOption (\r
4002 IN FORM_BROWSER_STATEMENT *Question,\r
4003 IN EFI_HII_VALUE *OptionValue\r
ee31d1be 4004 )\r
7c6c064c
ED
4005{\r
4006 LIST_ENTRY *Link;\r
4007 QUESTION_OPTION *Option;\r
4008 INTN Result;\r
4009\r
4010 Link = GetFirstNode (&Question->OptionListHead);\r
4011 while (!IsNull (&Question->OptionListHead, Link)) {\r
4012 Option = QUESTION_OPTION_FROM_LINK (Link);\r
4013\r
4014 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
4015 //\r
4016 // Check the suppressif condition, only a valid option can be return.\r
4017 //\r
4018 if ((Option->SuppressExpression == NULL) ||\r
4019 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
4020 return Option;\r
4021 }\r
4022 }\r
4023\r
4024 Link = GetNextNode (&Question->OptionListHead, Link);\r
ee31d1be 4025 }\r
7c6c064c
ED
4026\r
4027 return NULL;\r
ee31d1be 4028}\r
7936fb6a 4029\r
7c6c064c 4030\r
7936fb6a 4031/**\r
4032 Reset Question to its default value.\r
4033\r
4034 @param FormSet The form set.\r
4035 @param Form The form.\r
4036 @param Question The question.\r
4037 @param DefaultId The Class of the default.\r
4038\r
4039 @retval EFI_SUCCESS Question is reset to default value.\r
4040\r
4041**/\r
4042EFI_STATUS\r
4043GetQuestionDefault (\r
4044 IN FORM_BROWSER_FORMSET *FormSet,\r
4045 IN FORM_BROWSER_FORM *Form,\r
4046 IN FORM_BROWSER_STATEMENT *Question,\r
4047 IN UINT16 DefaultId\r
4048 )\r
4049{\r
4050 EFI_STATUS Status;\r
4051 LIST_ENTRY *Link;\r
4052 QUESTION_DEFAULT *Default;\r
4053 QUESTION_OPTION *Option;\r
4054 EFI_HII_VALUE *HiiValue;\r
4055 UINT8 Index;\r
086cd2c8 4056 EFI_STRING StrValue;\r
ee31d1be
ED
4057 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4058 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
4059 INTN Action;\r
061d5462 4060 CHAR16 *NewString;\r
7f36d629 4061 EFI_IFR_TYPE_VALUE *TypeValue;\r
75596726
DB
4062 UINT16 OriginalDefaultId;\r
4063 FORMSET_DEFAULTSTORE *DefaultStore;\r
4064 LIST_ENTRY *DefaultLink;\r
7936fb6a 4065\r
48a9d5f7 4066 Status = EFI_NOT_FOUND;\r
086cd2c8 4067 StrValue = NULL;\r
75596726
DB
4068 OriginalDefaultId = DefaultId;\r
4069 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
7936fb6a 4070\r
4071 //\r
4072 // Statement don't have storage, skip them\r
4073 //\r
4074 if (Question->QuestionId == 0) {\r
4075 return Status;\r
4076 }\r
4077\r
4078 //\r
ee31d1be
ED
4079 // There are Five ways to specify default value for a Question:\r
4080 // 1, use call back function (highest priority)\r
4081 // 2, use ExtractConfig function\r
4082 // 3, use nested EFI_IFR_DEFAULT \r
4083 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
4084 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 4085 //\r
75596726 4086ReGetDefault:\r
7936fb6a 4087 HiiValue = &Question->HiiValue;\r
7f36d629 4088 TypeValue = &HiiValue->Value;\r
fa8ee0ad 4089 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
7f36d629
DB
4090 //\r
4091 // For orderedlist, need to pass the BufferValue to Callback function.\r
4092 //\r
4093 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
4094 }\r
7936fb6a 4095\r
ee31d1be
ED
4096 //\r
4097 // Get Question defaut value from call back function.\r
4098 //\r
4099 ConfigAccess = FormSet->ConfigAccess;\r
4100 Action = GetDefaultIdForCallBack (DefaultId);\r
4101 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
4102 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
4103 Status = ConfigAccess->Callback (\r
4104 ConfigAccess,\r
4105 Action,\r
4106 Question->QuestionId,\r
4107 HiiValue->Type,\r
7f36d629 4108 TypeValue,\r
ee31d1be
ED
4109 &ActionRequest\r
4110 );\r
4111 if (!EFI_ERROR (Status)) {\r
061d5462
ED
4112 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
4113 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
4114 ASSERT (NewString != NULL);\r
4115\r
4116 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
4117 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
05b2f9c9 4118 ZeroMem (Question->BufferValue, Question->StorageWidth);\r
061d5462
ED
4119 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
4120 } else {\r
4121 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
4122 }\r
4123\r
4124 FreePool (NewString);\r
4125 }\r
ee31d1be
ED
4126 return Status;\r
4127 }\r
4128 }\r
4129\r
4130 //\r
4131 // Get default value from altcfg string.\r
4132 //\r
4133 if (ConfigAccess != NULL) { \r
7a9612ce 4134 Status = GetDefaultValueFromAltCfg(FormSet, Form, Question);\r
ee31d1be
ED
4135 if (!EFI_ERROR (Status)) {\r
4136 return Status;\r
4137 }\r
4138 }\r
4139\r
7936fb6a 4140 //\r
4141 // EFI_IFR_DEFAULT has highest priority\r
4142 //\r
4143 if (!IsListEmpty (&Question->DefaultListHead)) {\r
4144 Link = GetFirstNode (&Question->DefaultListHead);\r
4145 while (!IsNull (&Question->DefaultListHead, Link)) {\r
4146 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
4147\r
4148 if (Default->DefaultId == DefaultId) {\r
4149 if (Default->ValueExpression != NULL) {\r
4150 //\r
4151 // Default is provided by an Expression, evaluate it\r
4152 //\r
4153 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
4154 if (EFI_ERROR (Status)) {\r
4155 return Status;\r
4156 }\r
4157\r
901ba0e7
ED
4158 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
4159 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
4160 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
4161 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
4162 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
4163 } else {\r
4164 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
4165 Question->HiiValue.BufferLen = Question->StorageWidth;\r
4166 }\r
4167 FreePool (Default->ValueExpression->Result.Buffer);\r
4168 }\r
4169 HiiValue->Type = Default->ValueExpression->Result.Type;\r
4170 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 4171 } else {\r
4172 //\r
4173 // Default value is embedded in EFI_IFR_DEFAULT\r
4174 //\r
0b567d18
ED
4175 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
4176 ASSERT (HiiValue->Buffer != NULL);\r
4177 CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
4178 } else {\r
4179 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
4180 }\r
7936fb6a 4181 }\r
4182\r
086cd2c8
LG
4183 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
4184 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
4185 if (StrValue == NULL) {\r
4186 return EFI_NOT_FOUND;\r
4187 }\r
ba944801 4188 if (Question->StorageWidth > StrSize (StrValue)) {\r
05b2f9c9 4189 ZeroMem (Question->BufferValue, Question->StorageWidth);\r
ba944801
ED
4190 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
4191 } else {\r
4192 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
4193 }\r
086cd2c8
LG
4194 }\r
4195\r
7936fb6a 4196 return EFI_SUCCESS;\r
4197 }\r
4198\r
4199 Link = GetNextNode (&Question->DefaultListHead, Link);\r
4200 }\r
4201 }\r
4202\r
4203 //\r
4204 // EFI_ONE_OF_OPTION\r
4205 //\r
4206 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
4207 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
4208 //\r
4209 // OneOfOption could only provide Standard and Manufacturing default\r
4210 //\r
4211 Link = GetFirstNode (&Question->OptionListHead);\r
4212 while (!IsNull (&Question->OptionListHead, Link)) {\r
4213 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4214 Link = GetNextNode (&Question->OptionListHead, Link);\r
4215\r
4216 if ((Option->SuppressExpression != NULL) &&\r
4217 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4218 continue;\r
4219 }\r
7936fb6a 4220\r
4221 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
4222 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
4223 ) {\r
4224 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
4225\r
4226 return EFI_SUCCESS;\r
4227 }\r
7936fb6a 4228 }\r
4229 }\r
4230 }\r
4231\r
4232 //\r
4233 // EFI_IFR_CHECKBOX - lowest priority\r
4234 //\r
4235 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
4236 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
4237 //\r
4238 // Checkbox could only provide Standard and Manufacturing default\r
4239 //\r
4240 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
4241 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
4242 ) {\r
4243 HiiValue->Value.b = TRUE;\r
4244 } else {\r
4245 HiiValue->Value.b = FALSE;\r
4246 }\r
4247\r
4248 return EFI_SUCCESS;\r
4249 }\r
4250 }\r
4251\r
4252 //\r
75596726
DB
4253 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
4254 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
4255 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
4256 //\r
4257 while (!IsNull(&FormSet->DefaultStoreListHead, DefaultLink)) {\r
4258 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);\r
4259 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,DefaultLink);\r
4260 DefaultId = DefaultStore->DefaultId;\r
4261 if (DefaultId == OriginalDefaultId) {\r
4262 continue;\r
4263 }\r
4264 goto ReGetDefault;\r
4265 }\r
4266\r
4267 //\r
4268 // For Questions without default value for all the default id in the DefaultStoreList.\r
7936fb6a 4269 //\r
48a9d5f7 4270 Status = EFI_NOT_FOUND;\r
7936fb6a 4271 switch (Question->Operand) {\r
cf4c5a42
LG
4272 case EFI_IFR_NUMERIC_OP:\r
4273 //\r
4274 // Take minimum value as numeric default value\r
4275 //\r
afc9bf79
ED
4276 if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {\r
4277 //\r
4278 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
4279 //\r
4280 switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {\r
4281 case EFI_IFR_NUMERIC_SIZE_1:\r
4282 if (((INT8) HiiValue->Value.u8 < (INT8) Question->Minimum) || ((INT8) HiiValue->Value.u8 > (INT8) Question->Maximum)) {\r
4283 HiiValue->Value.u8 = (UINT8) Question->Minimum;\r
4284 Status = EFI_SUCCESS;\r
4285 }\r
4286 break;\r
4287 case EFI_IFR_NUMERIC_SIZE_2:\r
4288 if (((INT16) HiiValue->Value.u16 < (INT16) Question->Minimum) || ((INT16) HiiValue->Value.u16 > (INT16) Question->Maximum)) {\r
4289 HiiValue->Value.u16 = (UINT16) Question->Minimum;\r
4290 Status = EFI_SUCCESS;\r
4291 }\r
4292 break;\r
4293 case EFI_IFR_NUMERIC_SIZE_4:\r
4294 if (((INT32) HiiValue->Value.u32 < (INT32) Question->Minimum) || ((INT32) HiiValue->Value.u32 > (INT32) Question->Maximum)) {\r
4295 HiiValue->Value.u32 = (UINT32) Question->Minimum;\r
4296 Status = EFI_SUCCESS;\r
4297 }\r
4298 break;\r
4299 case EFI_IFR_NUMERIC_SIZE_8:\r
4300 if (((INT64) HiiValue->Value.u64 < (INT64) Question->Minimum) || ((INT64) HiiValue->Value.u64 > (INT64) Question->Maximum)) {\r
4301 HiiValue->Value.u64 = Question->Minimum;\r
4302 Status = EFI_SUCCESS;\r
4303 }\r
4304 break;\r
4305 default:\r
4306 break; \r
4307 }\r
4308 } else {\r
4309 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
4310 HiiValue->Value.u64 = Question->Minimum;\r
4311 Status = EFI_SUCCESS;\r
4312 }\r
cf4c5a42
LG
4313 }\r
4314 break;\r
4315\r
7936fb6a 4316 case EFI_IFR_ONE_OF_OP:\r
4317 //\r
4318 // Take first oneof option as oneof's default value\r
4319 //\r
d66e6c16 4320 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed 4321 Link = GetFirstNode (&Question->OptionListHead);\r
82612023 4322 while (!IsNull (&Question->OptionListHead, Link)) {\r
0a1147ed 4323 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4324 Link = GetNextNode (&Question->OptionListHead, Link);\r
4325\r
4326 if ((Option->SuppressExpression != NULL) &&\r
4327 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4328 continue;\r
4329 }\r
4330\r
0a1147ed 4331 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 4332 Status = EFI_SUCCESS;\r
82612023 4333 break;\r
0a1147ed 4334 }\r
7936fb6a 4335 }\r
4336 break;\r
4337\r
4338 case EFI_IFR_ORDERED_LIST_OP:\r
4339 //\r
4340 // Take option sequence in IFR as ordered list's default value\r
4341 //\r
4342 Index = 0;\r
4343 Link = GetFirstNode (&Question->OptionListHead);\r
4344 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 4345 Status = EFI_SUCCESS;\r
7936fb6a 4346 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4347 Link = GetNextNode (&Question->OptionListHead, Link);\r
4348\r
4349 if ((Option->SuppressExpression != NULL) &&\r
4350 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4351 continue;\r
4352 }\r
7936fb6a 4353\r
d02847d3 4354 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 4355\r
4356 Index++;\r
4357 if (Index >= Question->MaxContainers) {\r
4358 break;\r
4359 }\r
7936fb6a 4360 }\r
4361 break;\r
4362\r
4363 default:\r
7936fb6a 4364 break;\r
4365 }\r
4366\r
4367 return Status;\r
4368}\r
4369\r
7a9612ce
ED
4370/**\r
4371 Get AltCfg string for current form.\r
4372\r
4373 @param FormSet Form data structure.\r
4374 @param Form Form data structure.\r
4375 @param DefaultId The Class of the default.\r
787fc2a6 4376 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4377\r
4378**/\r
4379VOID\r
4380ExtractAltCfgForForm (\r
4381 IN FORM_BROWSER_FORMSET *FormSet,\r
4382 IN FORM_BROWSER_FORM *Form,\r
787fc2a6
ED
4383 IN UINT16 DefaultId,\r
4384 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4385 )\r
4386{\r
4387 EFI_STATUS Status;\r
4388 LIST_ENTRY *Link;\r
4389 CHAR16 *ConfigResp;\r
4390 CHAR16 *Progress;\r
4391 CHAR16 *Result;\r
4392 BROWSER_STORAGE *Storage;\r
4393 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4394 FORMSET_STORAGE *FormSetStorage;\r
4395\r
4396 //\r
4397 // Check whether has get AltCfg string for this formset.\r
4398 // If yes, no need to get AltCfg for form.\r
4399 //\r
4400 Link = GetFirstNode (&FormSet->StorageListHead);\r
4401 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4402 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4403 Storage = FormSetStorage->BrowserStorage;\r
4404 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
787fc2a6
ED
4405 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4406 continue;\r
4407 }\r
7a9612ce
ED
4408\r
4409 if (Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE &&\r
4410 FormSetStorage->ElementCount != 0 &&\r
787fc2a6 4411 FormSetStorage->HasCallAltCfg) {\r
7a9612ce
ED
4412 return;\r
4413 }\r
4414 }\r
4415\r
4416 //\r
4417 // Get AltCfg string for each form.\r
4418 //\r
4419 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4420 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4421 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4422 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4423\r
4424 Storage = ConfigInfo->Storage;\r
787fc2a6
ED
4425 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4426 continue;\r
4427 }\r
4428\r
7a9612ce
ED
4429 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4430 continue;\r
4431 }\r
4432\r
4433 //\r
4434 // 1. Skip if there is no RequestElement\r
4435 //\r
4436 if (ConfigInfo->ElementCount == 0) {\r
4437 continue;\r
4438 }\r
4439\r
4440 //\r
4441 // 2. Get value through hii config routine protocol.\r
4442 //\r
4443 Status = mHiiConfigRouting->ExtractConfig (\r
4444 mHiiConfigRouting,\r
4445 ConfigInfo->ConfigRequest,\r
4446 &Progress,\r
4447 &Result\r
4448 );\r
4449 if (EFI_ERROR (Status)) {\r
4450 continue;\r
4451 }\r
4452\r
4453 //\r
4454 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4455 // Get the default configuration string according to the default ID.\r
4456 //\r
4457 Status = mHiiConfigRouting->GetAltConfig (\r
4458 mHiiConfigRouting,\r
4459 Result,\r
4460 &Storage->Guid,\r
4461 Storage->Name,\r
4462 NULL,\r
4463 &DefaultId, // it can be NULL to get the current setting.\r
4464 &ConfigResp\r
4465 );\r
4466 FreePool (Result);\r
4467 if (EFI_ERROR (Status)) {\r
4468 continue;\r
4469 }\r
4470\r
4471 ConfigInfo->ConfigAltResp = ConfigResp;\r
4472 }\r
4473}\r
4474\r
4475/**\r
4476 Clean AltCfg string for current form.\r
4477\r
4478 @param Form Form data structure.\r
4479\r
4480**/\r
4481VOID\r
4482CleanAltCfgForForm (\r
4483 IN FORM_BROWSER_FORM *Form\r
4484 )\r
4485{\r
4486 LIST_ENTRY *Link;\r
4487 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4488\r
4489 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4490 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4491 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4492 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4493\r
4494 if (ConfigInfo->ConfigAltResp != NULL) {\r
4495 FreePool (ConfigInfo->ConfigAltResp);\r
4496 ConfigInfo->ConfigAltResp = NULL;\r
4497 }\r
4498 }\r
4499}\r
4500\r
4501/**\r
4502 Get AltCfg string for current formset.\r
4503\r
4504 @param FormSet Form data structure.\r
4505 @param DefaultId The Class of the default.\r
787fc2a6 4506 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4507\r
4508**/\r
4509VOID\r
4510ExtractAltCfgForFormSet (\r
4511 IN FORM_BROWSER_FORMSET *FormSet,\r
787fc2a6
ED
4512 IN UINT16 DefaultId,\r
4513 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4514 )\r
4515{\r
4516 EFI_STATUS Status;\r
4517 LIST_ENTRY *Link;\r
4518 CHAR16 *ConfigResp;\r
4519 CHAR16 *Progress;\r
4520 CHAR16 *Result;\r
4521 BROWSER_STORAGE *Storage;\r
4522 FORMSET_STORAGE *FormSetStorage;\r
4523\r
4524 Link = GetFirstNode (&FormSet->StorageListHead);\r
4525 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4526 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4527 Storage = FormSetStorage->BrowserStorage;\r
4528 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4529\r
787fc2a6
ED
4530 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4531 continue;\r
4532 }\r
4533\r
7a9612ce
ED
4534 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4535 continue;\r
4536 }\r
4537\r
4538 //\r
4539 // 1. Skip if there is no RequestElement\r
4540 //\r
4541 if (FormSetStorage->ElementCount == 0) {\r
4542 continue;\r
4543 }\r
4544\r
787fc2a6
ED
4545 FormSetStorage->HasCallAltCfg = TRUE;\r
4546\r
7a9612ce
ED
4547 //\r
4548 // 2. Get value through hii config routine protocol.\r
4549 //\r
4550 Status = mHiiConfigRouting->ExtractConfig (\r
4551 mHiiConfigRouting,\r
4552 FormSetStorage->ConfigRequest,\r
4553 &Progress,\r
4554 &Result\r
4555 );\r
4556 if (EFI_ERROR (Status)) {\r
4557 continue;\r
4558 }\r
4559\r
4560 //\r
4561 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4562 // Get the default configuration string according to the default ID.\r
4563 //\r
4564 Status = mHiiConfigRouting->GetAltConfig (\r
4565 mHiiConfigRouting,\r
4566 Result,\r
4567 &Storage->Guid,\r
4568 Storage->Name,\r
4569 NULL,\r
4570 &DefaultId, // it can be NULL to get the current setting.\r
4571 &ConfigResp\r
4572 );\r
4573\r
4574 FreePool (Result);\r
4575 if (EFI_ERROR (Status)) {\r
4576 continue;\r
4577 }\r
4578\r
4579 FormSetStorage->ConfigAltResp = ConfigResp;\r
4580 }\r
4581\r
4582}\r
4583\r
4584/**\r
4585 Clean AltCfg string for current formset.\r
4586\r
4587 @param FormSet Form data structure.\r
4588\r
4589**/\r
4590VOID\r
4591CleanAltCfgForFormSet (\r
4592 IN FORM_BROWSER_FORMSET *FormSet\r
4593 )\r
4594{\r
4595 LIST_ENTRY *Link;\r
4596 FORMSET_STORAGE *FormSetStorage;\r
4597\r
4598 Link = GetFirstNode (&FormSet->StorageListHead);\r
4599 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4600 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4601 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4602\r
4603 if (FormSetStorage->ConfigAltResp != NULL) {\r
4604 FreePool (FormSetStorage->ConfigAltResp);\r
4605 FormSetStorage->ConfigAltResp = NULL;\r
4606 }\r
787fc2a6
ED
4607\r
4608 FormSetStorage->HasCallAltCfg = FALSE;\r
7a9612ce
ED
4609 }\r
4610}\r
7936fb6a 4611\r
4612/**\r
9776099f 4613 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 4614\r
09cdd7d2
ED
4615 GetDefaultValueScope parameter decides which questions will reset \r
4616 to its default value.\r
4617\r
7936fb6a 4618 @param FormSet FormSet data structure.\r
48a9d5f7 4619 @param Form Form data structure.\r
7936fb6a 4620 @param DefaultId The Class of the default.\r
48a9d5f7 4621 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 4622 @param GetDefaultValueScope Get default value scope.\r
3347d410 4623 @param Storage Get default value only for this storage.\r
9776099f
ED
4624 @param RetrieveValueFirst Whether call the retrieve call back to\r
4625 get the initial value before get default\r
4626 value.\r
787fc2a6 4627 @param SkipGetAltCfg Whether skip the get altcfg string process.\r
7936fb6a 4628\r
4629 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 4630 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 4631\r
4632**/\r
4633EFI_STATUS\r
48a9d5f7 4634ExtractDefault (\r
7936fb6a 4635 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
4636 IN FORM_BROWSER_FORM *Form,\r
4637 IN UINT16 DefaultId,\r
3347d410 4638 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 4639 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
94f3aae7 4640 IN BROWSER_STORAGE *Storage OPTIONAL,\r
787fc2a6
ED
4641 IN BOOLEAN RetrieveValueFirst,\r
4642 IN BOOLEAN SkipGetAltCfg\r
7936fb6a 4643 )\r
4644{\r
4645 EFI_STATUS Status;\r
4f33c838 4646 LIST_ENTRY *FormLink;\r
48a9d5f7 4647 LIST_ENTRY *Link;\r
7936fb6a 4648 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7 4649 FORM_BROWSER_FORMSET *LocalFormSet;\r
6e74560f 4650 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 4651\r
9776099f
ED
4652 Status = EFI_SUCCESS;\r
4653\r
48a9d5f7
LG
4654 //\r
4655 // Check the supported setting level.\r
4656 //\r
09cdd7d2
ED
4657 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
4658 return EFI_UNSUPPORTED;\r
4659 }\r
4660\r
4661 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
4662 return EFI_UNSUPPORTED;\r
4663 }\r
7a9612ce 4664\r
48a9d5f7 4665 if (SettingScope == FormLevel) {\r
7a9612ce
ED
4666 //\r
4667 // Prepare the AltCfg String for form.\r
4668 //\r
787fc2a6
ED
4669 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4670 ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
4671 }\r
7a9612ce 4672\r
8d00a0f1 4673 //\r
4f33c838 4674 // Extract Form default\r
8d00a0f1 4675 //\r
48a9d5f7
LG
4676 Link = GetFirstNode (&Form->StatementListHead);\r
4677 while (!IsNull (&Form->StatementListHead, Link)) {\r
4678 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4679 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
4680\r
4681 //\r
4682 // If get default value only for this storage, check the storage first.\r
4683 //\r
09cdd7d2
ED
4684 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
4685 continue;\r
4686 }\r
4687\r
4688 //\r
4689 // If get default value only for no storage question, just skip the question which has storage.\r
4690 //\r
4691 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
4692 continue;\r
4693 }\r
4694\r
4f33c838
ED
4695 //\r
4696 // If Question is disabled, don't reset it to default\r
4697 //\r
31585af4
ED
4698 if (Question->Expression != NULL) {\r
4699 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
4700 continue;\r
4701 }\r
8d00a0f1 4702 }\r
9776099f
ED
4703\r
4704 if (RetrieveValueFirst) {\r
4705 //\r
4706 // Call the Retrieve call back to get the initial question value.\r
4707 //\r
061d5462 4708 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
9776099f
ED
4709 }\r
4710\r
4f33c838 4711 //\r
9776099f 4712 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 4713 //\r
9776099f
ED
4714 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
4715 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
4716 if (EFI_ERROR (Status)) {\r
4717 continue;\r
4718 }\r
4f33c838 4719 }\r
9776099f 4720\r
4f33c838
ED
4721 //\r
4722 // Synchronize Buffer storage's Edit buffer\r
4723 //\r
4724 if ((Question->Storage != NULL) &&\r
4725 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 4726 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
4727 }\r
4728 }\r
7a9612ce
ED
4729\r
4730 //\r
4731 // Clean the AltCfg String.\r
4732 //\r
787fc2a6
ED
4733 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4734 CleanAltCfgForForm(Form);\r
4735 }\r
48a9d5f7 4736 } else if (SettingScope == FormSetLevel) {\r
7a9612ce
ED
4737 //\r
4738 // Prepare the AltCfg String for formset.\r
4739 //\r
787fc2a6
ED
4740 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4741 ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
4742 }\r
7a9612ce 4743\r
48a9d5f7
LG
4744 FormLink = GetFirstNode (&FormSet->FormListHead);\r
4745 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
4746 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
787fc2a6 4747 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
48a9d5f7
LG
4748 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
4749 }\r
7a9612ce
ED
4750\r
4751 //\r
4752 // Clean the AltCfg String.\r
4753 //\r
787fc2a6
ED
4754 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4755 CleanAltCfgForFormSet (FormSet);\r
4756 }\r
48a9d5f7
LG
4757 } else if (SettingScope == SystemLevel) {\r
4758 //\r
7c6c064c 4759 // Preload all Hii formset.\r
48a9d5f7 4760 //\r
7c6c064c 4761 LoadAllHiiFormset();\r
6e74560f
ED
4762\r
4763 OldFormSet = mSystemLevelFormSet;\r
4764\r
48a9d5f7
LG
4765 //\r
4766 // Set Default Value for each FormSet in the maintain list.\r
4767 //\r
4768 Link = GetFirstNode (&gBrowserFormSetList);\r
4769 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4770 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 4771 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
4772 if (!ValidateFormSet(LocalFormSet)) {\r
4773 continue;\r
4774 }\r
6e74560f
ED
4775\r
4776 mSystemLevelFormSet = LocalFormSet;\r
4777\r
787fc2a6 4778 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
7936fb6a 4779 }\r
6e74560f
ED
4780\r
4781 mSystemLevelFormSet = OldFormSet;\r
7936fb6a 4782 }\r
4783\r
4784 return EFI_SUCCESS;\r
4785}\r
4786\r
7c6c064c
ED
4787\r
4788/**\r
4789 Validate whether this question's value has changed.\r
4790\r
4791 @param FormSet FormSet data structure.\r
4792 @param Form Form data structure.\r
4793 @param Question Question to be initialized.\r
4794 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
4795\r
4796 @retval TRUE Question's value has changed.\r
4797 @retval FALSE Question's value has not changed\r
4798\r
4799**/\r
4800BOOLEAN\r
4801IsQuestionValueChanged (\r
4802 IN FORM_BROWSER_FORMSET *FormSet,\r
4803 IN FORM_BROWSER_FORM *Form,\r
4804 IN OUT FORM_BROWSER_STATEMENT *Question,\r
4805 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
4806 )\r
4807{\r
4808 EFI_HII_VALUE BackUpValue;\r
4809 CHAR8 *BackUpBuffer;\r
4d4deaac
ED
4810 EFI_HII_VALUE BackUpValue2;\r
4811 CHAR8 *BackUpBuffer2;\r
7c6c064c
ED
4812 EFI_STATUS Status;\r
4813 BOOLEAN ValueChanged;\r
4814 UINTN BufferWidth;\r
4815\r
4816 //\r
4817 // For quetion without storage, always mark it as data not changed.\r
4818 //\r
4819 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
4820 return FALSE;\r
4821 }\r
4822\r
4823 BackUpBuffer = NULL;\r
4d4deaac 4824 BackUpBuffer2 = NULL;\r
7c6c064c
ED
4825 ValueChanged = FALSE;\r
4826\r
4827 switch (Question->Operand) {\r
4828 case EFI_IFR_ORDERED_LIST_OP:\r
4829 BufferWidth = Question->StorageWidth;\r
4830 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4831 ASSERT (BackUpBuffer != NULL);\r
4832 break;\r
4833\r
4834 case EFI_IFR_STRING_OP:\r
4835 case EFI_IFR_PASSWORD_OP:\r
4836 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4837 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4838 ASSERT (BackUpBuffer != NULL);\r
4839 break;\r
4840\r
4841 default:\r
4842 BufferWidth = 0;\r
4843 break;\r
4844 }\r
4845 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4846\r
4d4deaac
ED
4847 if (GetValueFrom == GetSetValueWithBothBuffer) {\r
4848 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4849 ASSERT_EFI_ERROR(Status);\r
7c6c064c 4850\r
4d4deaac
ED
4851 switch (Question->Operand) {\r
4852 case EFI_IFR_ORDERED_LIST_OP:\r
4853 BufferWidth = Question->StorageWidth;\r
4854 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4855 ASSERT (BackUpBuffer2 != NULL);\r
4856 break;\r
4857\r
4858 case EFI_IFR_STRING_OP:\r
4859 case EFI_IFR_PASSWORD_OP:\r
4860 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4861 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4862 ASSERT (BackUpBuffer2 != NULL);\r
4863 break;\r
4864\r
4865 default:\r
4866 BufferWidth = 0;\r
4867 break;\r
4868 }\r
4869 CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4870\r
4871 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
4872 ASSERT_EFI_ERROR(Status);\r
4873\r
4874 if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4875 CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
4876 ValueChanged = TRUE;\r
4877 }\r
4878 } else {\r
4879 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
4880 ASSERT_EFI_ERROR(Status);\r
4881\r
4882 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4883 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
4884 ValueChanged = TRUE;\r
4885 }\r
7c6c064c
ED
4886 }\r
4887\r
4888 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
7c6c064c 4889 if (BackUpBuffer != NULL) {\r
e77d2f9d 4890 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
7c6c064c
ED
4891 FreePool (BackUpBuffer);\r
4892 }\r
4893\r
4d4deaac
ED
4894 if (BackUpBuffer2 != NULL) {\r
4895 FreePool (BackUpBuffer2);\r
4896 }\r
4897\r
892eccc8
ED
4898 Question->ValueChanged = ValueChanged;\r
4899\r
7c6c064c
ED
4900 return ValueChanged;\r
4901}\r
4902\r
7936fb6a 4903/**\r
4904 Initialize Question's Edit copy from Storage.\r
4905\r
eccfeab1
LG
4906 @param Selection Selection contains the information about \r
4907 the Selection, form and formset to be displayed.\r
4908 Selection action may be updated in retrieve callback.\r
7d1b202d 4909 If Selection is NULL, only initialize Question value.\r
7936fb6a 4910 @param FormSet FormSet data structure.\r
4911 @param Form Form data structure.\r
4912\r
4913 @retval EFI_SUCCESS The function completed successfully.\r
4914\r
4915**/\r
4916EFI_STATUS\r
4917LoadFormConfig (\r
eccfeab1
LG
4918 IN OUT UI_MENU_SELECTION *Selection,\r
4919 IN FORM_BROWSER_FORMSET *FormSet,\r
4920 IN FORM_BROWSER_FORM *Form\r
7936fb6a 4921 )\r
4922{\r
eccfeab1
LG
4923 EFI_STATUS Status;\r
4924 LIST_ENTRY *Link;\r
4925 FORM_BROWSER_STATEMENT *Question;\r
eccfeab1 4926 \r
7936fb6a 4927 Link = GetFirstNode (&Form->StatementListHead);\r
4928 while (!IsNull (&Form->StatementListHead, Link)) {\r
4929 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4930\r
4931 //\r
4932 // Initialize local copy of Value for each Question\r
4933 //\r
7c6c064c
ED
4934 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
4935 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
4936 } else {\r
4937 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4938 }\r
7936fb6a 4939 if (EFI_ERROR (Status)) {\r
4940 return Status;\r
4941 }\r
e2100bfa
ED
4942\r
4943 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
4944 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
4945 }\r
4946\r
7936fb6a 4947 Link = GetNextNode (&Form->StatementListHead, Link);\r
4948 }\r
4949\r
4950 return EFI_SUCCESS;\r
4951}\r
4952\r
d66e6c16 4953/**\r
4954 Initialize Question's Edit copy from Storage for the whole Formset.\r
4955\r
eccfeab1
LG
4956 @param Selection Selection contains the information about \r
4957 the Selection, form and formset to be displayed.\r
4958 Selection action may be updated in retrieve callback.\r
7d1b202d 4959 If Selection is NULL, only initialize Question value.\r
d66e6c16 4960 @param FormSet FormSet data structure.\r
4961\r
4962 @retval EFI_SUCCESS The function completed successfully.\r
4963\r
4964**/\r
4965EFI_STATUS\r
4966LoadFormSetConfig (\r
eccfeab1
LG
4967 IN OUT UI_MENU_SELECTION *Selection,\r
4968 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 4969 )\r
4970{\r
eccfeab1
LG
4971 EFI_STATUS Status;\r
4972 LIST_ENTRY *Link;\r
4973 FORM_BROWSER_FORM *Form;\r
d66e6c16 4974\r
4975 Link = GetFirstNode (&FormSet->FormListHead);\r
4976 while (!IsNull (&FormSet->FormListHead, Link)) {\r
4977 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4978\r
4979 //\r
4980 // Initialize local copy of Value for each Form\r
4981 //\r
eccfeab1 4982 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 4983 if (EFI_ERROR (Status)) {\r
4984 return Status;\r
4985 }\r
4986\r
4987 Link = GetNextNode (&FormSet->FormListHead, Link);\r
4988 }\r
4989\r
7c6c064c
ED
4990 //\r
4991 // Finished question initialization.\r
4992 // \r
4993 FormSet->QuestionInited = TRUE;\r
4994\r
d66e6c16 4995 return EFI_SUCCESS;\r
4996}\r
4997\r
0a6f8af5
ED
4998/**\r
4999 Remove the Request element from the Config Request.\r
5000\r
5001 @param Storage Pointer to the browser storage.\r
5002 @param RequestElement The pointer to the Request element.\r
5003\r
5004**/\r
5005VOID\r
5006RemoveElement (\r
5007 IN OUT BROWSER_STORAGE *Storage,\r
5008 IN CHAR16 *RequestElement\r
5009 )\r
5010{\r
5011 CHAR16 *NewStr;\r
5012 CHAR16 *DestStr;\r
5013\r
5014 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
5015\r
5016 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
5017\r
5018 if (NewStr == NULL) {\r
5019 return;\r
5020 }\r
5021\r
5022 //\r
5023 // Remove this element from this ConfigRequest.\r
5024 //\r
5025 DestStr = NewStr;\r
5026 NewStr += StrLen (RequestElement);\r
5027 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
5028 \r
5029 Storage->SpareStrLen += StrLen (RequestElement); \r
5030}\r
5031\r
5032/**\r
5033 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
5034\r
a35ecb75 5035 @param Storage Pointer to the formset storage.\r
0a6f8af5
ED
5036 @param ConfigRequest The pointer to the Request element.\r
5037\r
5038**/\r
5039VOID\r
5040RemoveConfigRequest (\r
a35ecb75 5041 FORMSET_STORAGE *Storage,\r
0a6f8af5
ED
5042 CHAR16 *ConfigRequest\r
5043 )\r
5044{\r
5045 CHAR16 *RequestElement;\r
5046 CHAR16 *NextRequestElement;\r
5047 CHAR16 *SearchKey;\r
5048\r
7c6c064c
ED
5049 //\r
5050 // No request element in it, just return.\r
5051 //\r
5052 if (ConfigRequest == NULL) {\r
5053 return;\r
5054 }\r
5055\r
a35ecb75 5056 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
5057 //\r
5058 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
5059 //\r
5060 SearchKey = L"&";\r
5061 } else {\r
5062 //\r
5063 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
5064 //\r
5065 SearchKey = L"&OFFSET";\r
5066 }\r
5067\r
5068 //\r
5069 // Find SearchKey storage\r
5070 //\r
a35ecb75 5071 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
5072 RequestElement = StrStr (ConfigRequest, L"PATH");\r
5073 ASSERT (RequestElement != NULL);\r
5074 RequestElement = StrStr (RequestElement, SearchKey); \r
5075 } else {\r
5076 RequestElement = StrStr (ConfigRequest, SearchKey);\r
5077 }\r
5078\r
5079 while (RequestElement != NULL) {\r
5080 //\r
5081 // +1 to avoid find header itself.\r
5082 //\r
5083 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
5084\r
5085 //\r
5086 // The last Request element in configRequest string.\r
5087 //\r
5088 if (NextRequestElement != NULL) {\r
5089 //\r
5090 // Replace "&" with '\0'.\r
5091 //\r
5092 *NextRequestElement = L'\0';\r
5093 }\r
5094\r
a35ecb75 5095 RemoveElement (Storage->BrowserStorage, RequestElement);\r
0a6f8af5
ED
5096\r
5097 if (NextRequestElement != NULL) {\r
5098 //\r
5099 // Restore '&' with '\0' for later used.\r
5100 //\r
5101 *NextRequestElement = L'&';\r
5102 }\r
5103\r
5104 RequestElement = NextRequestElement;\r
5105 }\r
5106\r
5107 //\r
5108 // If no request element remain, just remove the ConfigRequest string.\r
5109 //\r
a35ecb75
ED
5110 if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
5111 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5112 Storage->BrowserStorage->ConfigRequest = NULL;\r
5113 Storage->BrowserStorage->SpareStrLen = 0;\r
0a6f8af5
ED
5114 }\r
5115}\r
5116\r
5117/**\r
5118 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
5119\r
5120 @param FormSet Pointer of the FormSet\r
5121\r
5122**/\r
5123VOID\r
5124CleanBrowserStorage (\r
5125 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5126 )\r
5127{\r
5128 LIST_ENTRY *Link;\r
5129 FORMSET_STORAGE *Storage;\r
5130\r
5131 Link = GetFirstNode (&FormSet->StorageListHead);\r
5132 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5133 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5134 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5135\r
fae73624
ED
5136 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
5137 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
5138 continue;\r
5139 }\r
0a6f8af5 5140\r
a35ecb75 5141 RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
fae73624
ED
5142 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
5143 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
5144 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
5145 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5dc6ab16 5146 Storage->BrowserStorage->ConfigRequest = NULL;\r
fae73624
ED
5147 }\r
5148 Storage->BrowserStorage->Initialized = FALSE;\r
0a6f8af5 5149 }\r
0a6f8af5
ED
5150 }\r
5151}\r
5152\r
efffd9c1
ED
5153/**\r
5154 Check whether current element in the ConfigReqeust string.\r
5155\r
5156 @param BrowserStorage Storage which includes ConfigReqeust.\r
5157 @param RequestElement New element need to check.\r
5158\r
5159 @retval TRUE The Element is in the ConfigReqeust string.\r
5160 @retval FALSE The Element not in the configReqeust String.\r
5161\r
5162**/\r
5163BOOLEAN \r
5164ElementValidation (\r
5165 BROWSER_STORAGE *BrowserStorage,\r
5166 CHAR16 *RequestElement\r
5167 )\r
5168{\r
5169 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
5170}\r
5171\r
5172/**\r
5173 Append the Request element to the Config Request.\r
5174\r
5175 @param ConfigRequest Current ConfigRequest info.\r
5176 @param SpareStrLen Current remain free buffer for config reqeust.\r
5177 @param RequestElement New Request element.\r
5178\r
5179**/\r
5180VOID\r
5181AppendConfigRequest (\r
5182 IN OUT CHAR16 **ConfigRequest,\r
5183 IN OUT UINTN *SpareStrLen,\r
5184 IN CHAR16 *RequestElement\r
5185 )\r
5186{\r
5187 CHAR16 *NewStr;\r
5188 UINTN StringSize;\r
5189 UINTN StrLength;\r
5ad66ec6 5190 UINTN MaxLen;\r
efffd9c1 5191\r
0a6f8af5 5192 StrLength = StrLen (RequestElement);\r
5ad66ec6
DB
5193 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
5194 MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
efffd9c1
ED
5195\r
5196 //\r
5197 // Append <RequestElement> to <ConfigRequest>\r
5198 //\r
5199 if (StrLength > *SpareStrLen) {\r
5200 //\r
5201 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
5202 //\r
5ad66ec6
DB
5203 MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
5204 NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
efffd9c1
ED
5205 ASSERT (NewStr != NULL);\r
5206\r
5207 if (*ConfigRequest != NULL) {\r
5208 CopyMem (NewStr, *ConfigRequest, StringSize);\r
5209 FreePool (*ConfigRequest);\r
5210 }\r
5211 *ConfigRequest = NewStr;\r
5212 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
5213 }\r
5214\r
5ad66ec6 5215 StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
efffd9c1
ED
5216 *SpareStrLen -= StrLength;\r
5217}\r
5218\r
5219/**\r
5220 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
5221\r
5222 @param Storage Form set Storage.\r
9d34cac8
ED
5223 @param Request The input request string.\r
5224 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
efffd9c1
ED
5225\r
5226 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
5227 @retval FALSE All elements covered by current used elements.\r
5228\r
5229**/\r
5230BOOLEAN \r
5231ConfigRequestAdjust (\r
9d34cac8
ED
5232 IN BROWSER_STORAGE *Storage,\r
5233 IN CHAR16 *Request,\r
5234 IN BOOLEAN RespString\r
efffd9c1
ED
5235 )\r
5236{\r
5237 CHAR16 *RequestElement;\r
5238 CHAR16 *NextRequestElement;\r
9d34cac8 5239 CHAR16 *NextElementBakup;\r
efffd9c1 5240 CHAR16 *SearchKey;\r
9d34cac8 5241 CHAR16 *ValueKey;\r
efffd9c1 5242 BOOLEAN RetVal;\r
9d34cac8 5243 CHAR16 *ConfigRequest;\r
efffd9c1 5244\r
efffd9c1 5245 RetVal = FALSE;\r
9d34cac8
ED
5246 NextElementBakup = NULL;\r
5247 ValueKey = NULL;\r
efffd9c1 5248\r
9d34cac8
ED
5249 if (Request != NULL) {\r
5250 ConfigRequest = Request;\r
5251 } else {\r
5252 ConfigRequest = Storage->ConfigRequest;\r
5253 }\r
5254\r
5255 if (Storage->ConfigRequest == NULL) {\r
5256 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
efffd9c1
ED
5257 return TRUE;\r
5258 }\r
5259\r
9d34cac8 5260 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
efffd9c1
ED
5261 //\r
5262 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
5263 //\r
5264 SearchKey = L"&";\r
5265 } else {\r
5266 //\r
5267 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
5268 //\r
5269 SearchKey = L"&OFFSET";\r
9d34cac8 5270 ValueKey = L"&VALUE";\r
efffd9c1
ED
5271 }\r
5272\r
efffd9c1
ED
5273 //\r
5274 // Find SearchKey storage\r
5275 //\r
9d34cac8
ED
5276 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
5277 RequestElement = StrStr (ConfigRequest, L"PATH");\r
efffd9c1
ED
5278 ASSERT (RequestElement != NULL);\r
5279 RequestElement = StrStr (RequestElement, SearchKey); \r
5280 } else {\r
9d34cac8 5281 RequestElement = StrStr (ConfigRequest, SearchKey);\r
efffd9c1
ED
5282 }\r
5283\r
5284 while (RequestElement != NULL) {\r
9d34cac8 5285\r
efffd9c1
ED
5286 //\r
5287 // +1 to avoid find header itself.\r
5288 //\r
5289 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
5290\r
5291 //\r
5292 // The last Request element in configRequest string.\r
5293 //\r
5294 if (NextRequestElement != NULL) {\r
9d34cac8
ED
5295 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5296 NextElementBakup = NextRequestElement;\r
5297 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 5298 ASSERT (NextRequestElement != NULL);\r
9d34cac8 5299 }\r
efffd9c1
ED
5300 //\r
5301 // Replace "&" with '\0'.\r
5302 //\r
5303 *NextRequestElement = L'\0';\r
9d34cac8
ED
5304 } else {\r
5305 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5306 NextElementBakup = NextRequestElement;\r
5307 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 5308 ASSERT (NextRequestElement != NULL);\r
9d34cac8
ED
5309 //\r
5310 // Replace "&" with '\0'.\r
5311 //\r
5312 *NextRequestElement = L'\0';\r
5313 }\r
efffd9c1
ED
5314 }\r
5315 \r
9d34cac8 5316 if (!ElementValidation (Storage, RequestElement)) {\r
efffd9c1
ED
5317 //\r
5318 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
5319 //\r
9d34cac8 5320 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
efffd9c1
ED
5321 RetVal = TRUE;\r
5322 }\r
5323\r
5324 if (NextRequestElement != NULL) {\r
5325 //\r
5326 // Restore '&' with '\0' for later used.\r
5327 //\r
5328 *NextRequestElement = L'&';\r
5329 }\r
5330\r
9d34cac8
ED
5331 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5332 RequestElement = NextElementBakup;\r
5333 } else {\r
5334 RequestElement = NextRequestElement;\r
7c6c064c 5335 }\r
efffd9c1
ED
5336 }\r
5337\r
5338 return RetVal;\r
5339}\r
5340\r
7936fb6a 5341/**\r
5342 Fill storage's edit copy with settings requested from Configuration Driver.\r
5343\r
5344 @param FormSet FormSet data structure.\r
5345 @param Storage Buffer Storage.\r
5346\r
7936fb6a 5347**/\r
7c6c064c 5348VOID\r
7936fb6a 5349LoadStorage (\r
5350 IN FORM_BROWSER_FORMSET *FormSet,\r
5351 IN FORMSET_STORAGE *Storage\r
5352 )\r
5353{\r
5354 EFI_STATUS Status;\r
5355 EFI_STRING Progress;\r
5356 EFI_STRING Result;\r
5357 CHAR16 *StrPtr;\r
98c4caa1
ED
5358 EFI_STRING ConfigRequest;\r
5359 UINTN StrLen;\r
5360\r
5361 ConfigRequest = NULL;\r
7936fb6a 5362\r
7c6c064c
ED
5363 switch (Storage->BrowserStorage->Type) {\r
5364 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
5365 return;\r
5366\r
5367 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
6e74560f 5368 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
9d34cac8 5369 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
7c6c064c
ED
5370 return;\r
5371 }\r
7c6c064c 5372 break;\r
cce6230f 5373\r
7c6c064c
ED
5374 case EFI_HII_VARSTORE_BUFFER:\r
5375 case EFI_HII_VARSTORE_NAME_VALUE:\r
5376 //\r
27c304f4 5377 // Skip if there is no RequestElement.\r
7c6c064c 5378 //\r
27c304f4 5379 if (Storage->ElementCount == 0) {\r
7c6c064c
ED
5380 return;\r
5381 }\r
27c304f4
ED
5382\r
5383 //\r
5384 // Just update the ConfigRequest, if storage already initialized. \r
5385 //\r
5386 if (Storage->BrowserStorage->Initialized) {\r
9d34cac8 5387 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
27c304f4
ED
5388 return;\r
5389 }\r
5390\r
fae73624 5391 Storage->BrowserStorage->Initialized = TRUE;\r
7c6c064c 5392 break;\r
7936fb6a 5393\r
7c6c064c 5394 default:\r
7248790e 5395 return;\r
7936fb6a 5396 }\r
7248790e 5397\r
27c304f4
ED
5398 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
5399 //\r
5400 // Create the config request string to get all fields for this storage.\r
5401 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
5402 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
5403 //\r
a35ecb75 5404 StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
27c304f4
ED
5405 ConfigRequest = AllocateZeroPool (StrLen);\r
5406 ASSERT (ConfigRequest != NULL);\r
5407 UnicodeSPrint (\r
5408 ConfigRequest, \r
5409 StrLen, \r
5410 L"%s&OFFSET=0&WIDTH=%04x", \r
a35ecb75 5411 Storage->ConfigHdr,\r
27c304f4
ED
5412 Storage->BrowserStorage->Size);\r
5413 } else {\r
5414 ConfigRequest = Storage->ConfigRequest;\r
5415 }\r
5416\r
7248790e
ED
5417 //\r
5418 // Request current settings from Configuration Driver\r
5419 //\r
5420 Status = mHiiConfigRouting->ExtractConfig (\r
5421 mHiiConfigRouting,\r
98c4caa1 5422 ConfigRequest,\r
7248790e
ED
5423 &Progress,\r
5424 &Result\r
5425 );\r
5426\r
5427 //\r
5428 // If get value fail, extract default from IFR binary\r
5429 //\r
5430 if (EFI_ERROR (Status)) {\r
787fc2a6 5431 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
7248790e
ED
5432 } else {\r
5433 //\r
5434 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
5435 //\r
5436 StrPtr = StrStr (Result, L"&GUID=");\r
5437 if (StrPtr != NULL) {\r
5438 *StrPtr = L'\0';\r
5439 }\r
5440 \r
5441 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
5442 FreePool (Result);\r
5443 }\r
5444\r
5445 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
5446\r
5447 //\r
5448 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
5449 //\r
4d4deaac 5450 SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
98c4caa1 5451\r
27c304f4 5452 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
98c4caa1
ED
5453 if (ConfigRequest != NULL) {\r
5454 FreePool (ConfigRequest);\r
5455 }\r
5456 }\r
7936fb6a 5457}\r
5458\r
892eccc8
ED
5459/**\r
5460 Get Value changed status from old question.\r
5461\r
5462 @param NewFormSet FormSet data structure.\r
5463 @param OldQuestion Old question which has value changed.\r
5464\r
5465**/\r
5466VOID\r
5467SyncStatusForQuestion (\r
5468 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5469 IN FORM_BROWSER_STATEMENT *OldQuestion\r
5470 )\r
5471{\r
5472 LIST_ENTRY *Link;\r
5473 LIST_ENTRY *QuestionLink;\r
5474 FORM_BROWSER_FORM *Form;\r
5475 FORM_BROWSER_STATEMENT *Question;\r
5476\r
5477 //\r
5478 // For each form in one formset.\r
5479 //\r
5480 Link = GetFirstNode (&NewFormSet->FormListHead);\r
5481 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
5482 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5483 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
5484\r
5485 //\r
5486 // for each question in one form.\r
5487 //\r
5488 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5489 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5490 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5491 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5492\r
5493 if (Question->QuestionId == OldQuestion->QuestionId) {\r
5494 Question->ValueChanged = TRUE;\r
5495 return;\r
5496 }\r
5497 }\r
5498 }\r
5499}\r
5500\r
5501/**\r
5502 Get Value changed status from old formset.\r
5503\r
5504 @param NewFormSet FormSet data structure.\r
5505 @param OldFormSet FormSet data structure.\r
5506\r
5507**/\r
5508VOID\r
5509SyncStatusForFormSet (\r
5510 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5511 IN FORM_BROWSER_FORMSET *OldFormSet\r
5512 )\r
5513{\r
5514 LIST_ENTRY *Link;\r
5515 LIST_ENTRY *QuestionLink;\r
5516 FORM_BROWSER_FORM *Form;\r
5517 FORM_BROWSER_STATEMENT *Question;\r
5518\r
5519 //\r
5520 // For each form in one formset.\r
5521 //\r
5522 Link = GetFirstNode (&OldFormSet->FormListHead);\r
5523 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
5524 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5525 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
5526\r
5527 //\r
5528 // for each question in one form.\r
5529 //\r
5530 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5531 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5532 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5533 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5534\r
5535 if (!Question->ValueChanged) {\r
5536 continue;\r
5537 }\r
5538\r
5539 //\r
5540 // Find the same question in new formset and update the value changed flag.\r
5541 //\r
5542 SyncStatusForQuestion (NewFormSet, Question);\r
5543 }\r
5544 }\r
5545}\r
5546\r
7936fb6a 5547/**\r
5548 Get current setting of Questions.\r
5549\r
5550 @param FormSet FormSet data structure.\r
5551\r
7936fb6a 5552**/\r
7c6c064c 5553VOID\r
7936fb6a 5554InitializeCurrentSetting (\r
5555 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5556 )\r
5557{\r
5558 LIST_ENTRY *Link;\r
5559 FORMSET_STORAGE *Storage;\r
7c6c064c 5560 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 5561\r
6e74560f
ED
5562 //\r
5563 // Try to find pre FormSet in the maintain backup list.\r
5564 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
5565 //\r
5566 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
5567 if (OldFormSet != NULL) {\r
892eccc8 5568 SyncStatusForFormSet (FormSet, OldFormSet);\r
6e74560f
ED
5569 RemoveEntryList (&OldFormSet->Link);\r
5570 DestroyFormSet (OldFormSet);\r
5571 }\r
5572 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
5573\r
1deb5cab
ED
5574 //\r
5575 // Extract default from IFR binary for no storage questions.\r
5576 // \r
787fc2a6 5577 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\r
1deb5cab 5578\r
7936fb6a 5579 //\r
5580 // Request current settings from Configuration Driver\r
5581 //\r
5582 Link = GetFirstNode (&FormSet->StorageListHead);\r
5583 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5584 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5585\r
7c6c064c 5586 LoadStorage (FormSet, Storage);\r
7936fb6a 5587\r
7936fb6a 5588 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5589 }\r
7936fb6a 5590}\r
5591\r
5592\r
5593/**\r
5594 Fetch the Ifr binary data of a FormSet.\r
5595\r
5596 @param Handle PackageList Handle\r
f5006bd9 5597 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5598 specified (NULL or zero GUID), take the first\r
5599 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5600 found in package list.\r
5601 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5602 @param BinaryLength The length of the FormSet IFR binary.\r
5603 @param BinaryData The buffer designed to receive the FormSet.\r
5604\r
5605 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
5606 BufferLength was updated.\r
5607 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
5608 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
5609 be found with the requested FormId.\r
5610\r
5611**/\r
5612EFI_STATUS\r
5613GetIfrBinaryData (\r
5614 IN EFI_HII_HANDLE Handle,\r
5615 IN OUT EFI_GUID *FormSetGuid,\r
5616 OUT UINTN *BinaryLength,\r
5617 OUT UINT8 **BinaryData\r
5618 )\r
5619{\r
5620 EFI_STATUS Status;\r
5621 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
5622 UINTN BufferSize;\r
5623 UINT8 *Package;\r
5624 UINT8 *OpCodeData;\r
5625 UINT32 Offset;\r
5626 UINT32 Offset2;\r
7936fb6a 5627 UINT32 PackageListLength;\r
5628 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
5629 UINT8 Index;\r
5630 UINT8 NumberOfClassGuid;\r
f5006bd9 5631 BOOLEAN ClassGuidMatch;\r
0a1147ed 5632 EFI_GUID *ClassGuid;\r
f5006bd9 5633 EFI_GUID *ComparingGuid;\r
7936fb6a 5634\r
5635 OpCodeData = NULL;\r
5636 Package = NULL;\r
0c66bc76 5637 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 5638\r
5639 //\r
f5006bd9 5640 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 5641 //\r
48a9d5f7
LG
5642 if (FormSetGuid == NULL) {\r
5643 ComparingGuid = &gZeroGuid;\r
7936fb6a 5644 } else {\r
f5006bd9 5645 ComparingGuid = FormSetGuid;\r
7936fb6a 5646 }\r
5647\r
5648 //\r
5649 // Get HII PackageList\r
5650 //\r
5651 BufferSize = 0;\r
5652 HiiPackageList = NULL;\r
5653 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5654 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5655 HiiPackageList = AllocatePool (BufferSize);\r
5656 ASSERT (HiiPackageList != NULL);\r
5657\r
5658 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5659 }\r
5660 if (EFI_ERROR (Status)) {\r
5661 return Status;\r
5662 }\r
db0bd81c 5663 ASSERT (HiiPackageList != NULL);\r
d66e6c16 5664\r
7936fb6a 5665 //\r
5666 // Get Form package from this HII package List\r
5667 //\r
5668 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
5669 Offset2 = 0;\r
5670 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
5671\r
f5006bd9 5672 ClassGuidMatch = FALSE;\r
7936fb6a 5673 while (Offset < PackageListLength) {\r
5674 Package = ((UINT8 *) HiiPackageList) + Offset;\r
5675 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
5676\r
8d00a0f1 5677 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 5678 //\r
5679 // Search FormSet in this Form Package\r
5680 //\r
5681 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
5682 while (Offset2 < PackageHeader.Length) {\r
5683 OpCodeData = Package + Offset2;\r
5684\r
5685 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
5686 //\r
f5006bd9 5687 // Try to compare against formset GUID\r
7936fb6a 5688 //\r
48a9d5f7
LG
5689 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
5690 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 5691 break;\r
7936fb6a 5692 }\r
5693\r
d228526f
LG
5694 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
5695 //\r
5696 // Try to compare against formset class GUID\r
5697 //\r
5698 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
5699 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
5700 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
5701 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
5702 ClassGuidMatch = TRUE;\r
5703 break;\r
5704 }\r
5705 }\r
5706 if (ClassGuidMatch) {\r
f5006bd9 5707 break;\r
5708 }\r
d228526f
LG
5709 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
5710 ClassGuidMatch = TRUE;\r
7936fb6a 5711 break;\r
5712 }\r
5713 }\r
5714\r
5715 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
5716 }\r
5717\r
5718 if (Offset2 < PackageHeader.Length) {\r
5719 //\r
5720 // Target formset found\r
5721 //\r
5722 break;\r
5723 }\r
5724 }\r
5725\r
5726 Offset += PackageHeader.Length;\r
5727 }\r
5728\r
5729 if (Offset >= PackageListLength) {\r
5730 //\r
5731 // Form package not found in this Package List\r
5732 //\r
f4113e1f 5733 FreePool (HiiPackageList);\r
7936fb6a 5734 return EFI_NOT_FOUND;\r
5735 }\r
5736\r
48a9d5f7 5737 if (FormSetGuid != NULL) {\r
7936fb6a 5738 //\r
f5006bd9 5739 // Return the FormSet GUID\r
7936fb6a 5740 //\r
5741 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
5742 }\r
5743\r
5744 //\r
5745 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
5746 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
5747 // of the Form Package.\r
5748 //\r
5749 *BinaryLength = PackageHeader.Length - Offset2;\r
5750 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
5751\r
f4113e1f 5752 FreePool (HiiPackageList);\r
7936fb6a 5753\r
5754 if (*BinaryData == NULL) {\r
5755 return EFI_OUT_OF_RESOURCES;\r
5756 }\r
5757\r
5758 return EFI_SUCCESS;\r
5759}\r
5760\r
5761\r
5762/**\r
5763 Initialize the internal data structure of a FormSet.\r
5764\r
5765 @param Handle PackageList Handle\r
f5006bd9 5766 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5767 specified (NULL or zero GUID), take the first\r
5768 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5769 found in package list.\r
5770 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5771 @param FormSet FormSet data structure.\r
5772\r
5773 @retval EFI_SUCCESS The function completed successfully.\r
5774 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
5775\r
5776**/\r
5777EFI_STATUS\r
5778InitializeFormSet (\r
5779 IN EFI_HII_HANDLE Handle,\r
5780 IN OUT EFI_GUID *FormSetGuid,\r
7c6c064c 5781 OUT FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 5782 )\r
5783{\r
5784 EFI_STATUS Status;\r
5785 EFI_HANDLE DriverHandle;\r
7936fb6a 5786\r
5787 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
5788 if (EFI_ERROR (Status)) {\r
5789 return Status;\r
5790 }\r
5791\r
48a9d5f7 5792 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 5793 FormSet->HiiHandle = Handle;\r
5794 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
7c6c064c 5795 FormSet->QuestionInited = FALSE;\r
7936fb6a 5796\r
5797 //\r
5798 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
5799 //\r
5800 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
5801 if (EFI_ERROR (Status)) {\r
5802 return Status;\r
5803 }\r
5804 FormSet->DriverHandle = DriverHandle;\r
5805 Status = gBS->HandleProtocol (\r
5806 DriverHandle,\r
5807 &gEfiHiiConfigAccessProtocolGuid,\r
5808 (VOID **) &FormSet->ConfigAccess\r
5809 );\r
5810 if (EFI_ERROR (Status)) {\r
5811 //\r
5812 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
5813 // list, then there will be no configuration action required\r
5814 //\r
5815 FormSet->ConfigAccess = NULL;\r
5816 }\r
5817\r
5818 //\r
5819 // Parse the IFR binary OpCodes\r
5820 //\r
5821 Status = ParseOpCodes (FormSet);\r
25361615 5822\r
7c6c064c 5823 return Status;\r
7936fb6a 5824}\r
ce6d12cc 5825\r
5826\r
5827/**\r
5828 Save globals used by previous call to SendForm(). SendForm() may be called from \r
5829 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
5830 So, save globals of previous call to SendForm() and restore them upon exit.\r
5831\r
5832**/\r
5833VOID\r
5834SaveBrowserContext (\r
5835 VOID\r
5836 )\r
5837{\r
b6f61255
ED
5838 BROWSER_CONTEXT *Context;\r
5839 FORM_ENTRY_INFO *MenuList;\r
5840 FORM_BROWSER_FORMSET *FormSet;\r
ce6d12cc 5841\r
5842 gBrowserContextCount++;\r
5843 if (gBrowserContextCount == 1) {\r
5844 //\r
5845 // This is not reentry of SendForm(), no context to save\r
5846 //\r
5847 return;\r
5848 }\r
5849\r
5850 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
5851 ASSERT (Context != NULL);\r
5852\r
5853 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
5854\r
5855 //\r
5856 // Save FormBrowser context\r
5857 //\r
5a9f73bf 5858 Context->Selection = gCurrentSelection;\r
ce6d12cc 5859 Context->ResetRequired = gResetRequired;\r
f2e7732e
ED
5860 Context->FlagReconnect = gFlagReconnect;\r
5861 Context->CallbackReconnect = gCallbackReconnect;\r
7c6c064c
ED
5862 Context->ExitRequired = gExitRequired;\r
5863 Context->HiiHandle = mCurrentHiiHandle;\r
5a9f73bf
ED
5864 Context->FormId = mCurrentFormId;\r
5865 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
f4c3c923
ED
5866 Context->SystemLevelFormSet = mSystemLevelFormSet;\r
5867 Context->CurFakeQestId = mCurFakeQestId;\r
5868 Context->HiiPackageListUpdated = mHiiPackageListUpdated;\r
5869 Context->FinishRetrieveCall = mFinishRetrieveCall;\r
7c6c064c
ED
5870\r
5871 //\r
5872 // Save the menu history data.\r
5873 //\r
5874 InitializeListHead(&Context->FormHistoryList);\r
5875 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
5876 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
5877 RemoveEntryList (&MenuList->Link);\r
5878\r
5879 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
5880 }\r
ce6d12cc 5881\r
b6f61255
ED
5882 //\r
5883 // Save formset list.\r
5884 //\r
5885 InitializeListHead(&Context->FormSetList);\r
5886 while (!IsListEmpty (&gBrowserFormSetList)) {\r
5887 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList.ForwardLink);\r
5888 RemoveEntryList (&FormSet->Link);\r
5889\r
5890 InsertTailList(&Context->FormSetList, &FormSet->Link);\r
5891 }\r
5892\r
ce6d12cc 5893 //\r
5894 // Insert to FormBrowser context list\r
5895 //\r
5896 InsertHeadList (&gBrowserContextList, &Context->Link);\r
5897}\r
5898\r
5899\r
5900/**\r
5901 Restore globals used by previous call to SendForm().\r
5902\r
5903**/\r
5904VOID\r
5905RestoreBrowserContext (\r
5906 VOID\r
5907 )\r
5908{\r
5909 LIST_ENTRY *Link;\r
5910 BROWSER_CONTEXT *Context;\r
b6f61255
ED
5911 FORM_ENTRY_INFO *MenuList;\r
5912 FORM_BROWSER_FORMSET *FormSet;\r
ce6d12cc 5913\r
5914 ASSERT (gBrowserContextCount != 0);\r
5915 gBrowserContextCount--;\r
5916 if (gBrowserContextCount == 0) {\r
5917 //\r
5918 // This is not reentry of SendForm(), no context to restore\r
5919 //\r
5920 return;\r
5921 }\r
5922\r
5923 ASSERT (!IsListEmpty (&gBrowserContextList));\r
5924\r
5925 Link = GetFirstNode (&gBrowserContextList);\r
5926 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5927\r
5928 //\r
5929 // Restore FormBrowser context\r
5930 //\r
5a9f73bf 5931 gCurrentSelection = Context->Selection;\r
ce6d12cc 5932 gResetRequired = Context->ResetRequired;\r
f2e7732e
ED
5933 gFlagReconnect = Context->FlagReconnect;\r
5934 gCallbackReconnect = Context->CallbackReconnect;\r
7c6c064c
ED
5935 gExitRequired = Context->ExitRequired;\r
5936 mCurrentHiiHandle = Context->HiiHandle;\r
5a9f73bf
ED
5937 mCurrentFormId = Context->FormId;\r
5938 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
f4c3c923
ED
5939 mSystemLevelFormSet = Context->SystemLevelFormSet;\r
5940 mCurFakeQestId = Context->CurFakeQestId;\r
5941 mHiiPackageListUpdated = Context->HiiPackageListUpdated;\r
5942 mFinishRetrieveCall = Context->FinishRetrieveCall;\r
7c6c064c
ED
5943\r
5944 //\r
5945 // Restore the menu history data.\r
5946 //\r
5947 while (!IsListEmpty (&Context->FormHistoryList)) {\r
5948 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
5949 RemoveEntryList (&MenuList->Link);\r
5950\r
5951 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
5952 }\r
ce6d12cc 5953\r
b6f61255
ED
5954 //\r
5955 // Restore the Formset data.\r
5956 //\r
5957 while (!IsListEmpty (&Context->FormSetList)) {\r
5958 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Context->FormSetList.ForwardLink);\r
5959 RemoveEntryList (&FormSet->Link);\r
5960\r
5961 InsertTailList(&gBrowserFormSetList, &FormSet->Link);\r
5962 }\r
5963\r
ce6d12cc 5964 //\r
5965 // Remove from FormBrowser context list\r
5966 //\r
5967 RemoveEntryList (&Context->Link);\r
5968 gBS->FreePool (Context);\r
5969}\r
48a9d5f7
LG
5970\r
5971/**\r
5972 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
5973 \r
5974 @param Handle The Hii Handle.\r
5975 \r
5976 @return the found FormSet context. If no found, NULL will return.\r
5977\r
5978**/\r
5979FORM_BROWSER_FORMSET * \r
5980GetFormSetFromHiiHandle (\r
5981 EFI_HII_HANDLE Handle\r
5982 )\r
5983{\r
5984 LIST_ENTRY *Link;\r
5985 FORM_BROWSER_FORMSET *FormSet;\r
5986\r
5987 Link = GetFirstNode (&gBrowserFormSetList);\r
5988 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5989 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
5990 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5991 if (!ValidateFormSet(FormSet)) {\r
5992 continue;\r
5993 }\r
48a9d5f7
LG
5994 if (FormSet->HiiHandle == Handle) {\r
5995 return FormSet;\r
5996 }\r
48a9d5f7
LG
5997 }\r
5998 \r
5999 return NULL;\r
6000}\r
6001\r
6002/**\r
6003 Check whether the input HII handle is the FormSet that is being used.\r
6004 \r
6005 @param Handle The Hii Handle.\r
6006 \r
6007 @retval TRUE HII handle is being used.\r
6008 @retval FALSE HII handle is not being used.\r
6009\r
6010**/\r
6011BOOLEAN\r
6012IsHiiHandleInBrowserContext (\r
6013 EFI_HII_HANDLE Handle\r
6014 )\r
6015{\r
6016 LIST_ENTRY *Link;\r
6017 BROWSER_CONTEXT *Context;\r
6018\r
6019 //\r
6020 // HiiHandle is Current FormSet.\r
6021 //\r
7c6c064c 6022 if (mCurrentHiiHandle == Handle) {\r
48a9d5f7
LG
6023 return TRUE;\r
6024 }\r
6025\r
6026 //\r
6027 // Check whether HiiHandle is in BrowserContext.\r
6028 //\r
6029 Link = GetFirstNode (&gBrowserContextList);\r
6030 while (!IsNull (&gBrowserContextList, Link)) {\r
6031 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
7c6c064c 6032 if (Context->HiiHandle == Handle) {\r
48a9d5f7
LG
6033 //\r
6034 // HiiHandle is in BrowserContext\r
6035 //\r
6036 return TRUE;\r
6037 }\r
6038 Link = GetNextNode (&gBrowserContextList, Link);\r
6039 }\r
6040 \r
6041 return FALSE;\r
6042}\r
6043\r
7c6c064c
ED
6044/**\r
6045 Perform Password check. \r
6046 Passwork may be encrypted by driver that requires the specific check.\r
6047 \r
6048 @param Form Form where Password Statement is in.\r
6049 @param Statement Password statement\r
6050 @param PasswordString Password string to be checked. It may be NULL.\r
6051 NULL means to restore password.\r
6052 "" string can be used to checked whether old password does exist.\r
6053 \r
6054 @return Status Status of Password check.\r
6055**/\r
6056EFI_STATUS\r
6057EFIAPI\r
6058PasswordCheck (\r
6059 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
6060 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
6061 IN EFI_STRING PasswordString OPTIONAL\r
6062 )\r
6063{\r
6064 EFI_STATUS Status;\r
6065 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
6066 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
6067 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
6068 FORM_BROWSER_STATEMENT *Question;\r
6069\r
6070 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
6071 Question = GetBrowserStatement(Statement);\r
6072 ASSERT (Question != NULL);\r
6073\r
6074 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
6075 if (ConfigAccess == NULL) {\r
6076 return EFI_UNSUPPORTED;\r
6077 }\r
6078 } else {\r
6079 if (PasswordString == NULL) {\r
6080 return EFI_SUCCESS;\r
6081 } \r
27582c41
ED
6082\r
6083 //\r
6084 // Check whether has preexisted password.\r
6085 //\r
6086 if (PasswordString[0] == 0) {\r
6087 if (*((CHAR16 *) Question->BufferValue) == 0) {\r
6088 return EFI_SUCCESS;\r
6089 } else {\r
6090 return EFI_NOT_READY;\r
6091 }\r
6092 }\r
6093\r
6094 //\r
6095 // Check whether the input password is same as preexisted password.\r
6096 //\r
7c6c064c
ED
6097 if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
6098 return EFI_SUCCESS;\r
6099 } else {\r
6100 return EFI_NOT_READY;\r
6101 }\r
6102 }\r
6103 \r
6104 //\r
6105 // Prepare password string in HII database\r
6106 //\r
6107 if (PasswordString != NULL) {\r
6108 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
6109 } else {\r
6110 IfrTypeValue.string = 0;\r
6111 }\r
6112\r
6113 //\r
6114 // Send password to Configuration Driver for validation\r
6115 //\r
6116 Status = ConfigAccess->Callback (\r
6117 ConfigAccess,\r
6118 EFI_BROWSER_ACTION_CHANGING,\r
6119 Question->QuestionId,\r
6120 Question->HiiValue.Type,\r
6121 &IfrTypeValue,\r
6122 &ActionRequest\r
6123 );\r
6124\r
6125 //\r
6126 // Remove password string from HII database\r
6127 //\r
6128 if (PasswordString != NULL) {\r
6129 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
6130 }\r
6131\r
6132 return Status;\r
6133}\r
6134\r
48a9d5f7
LG
6135/**\r
6136 Find the registered HotKey based on KeyData.\r
6137 \r
6138 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
6139 information for the hot key.\r
6140\r
6141 @return The registered HotKey context. If no found, NULL will return.\r
6142**/\r
6143BROWSER_HOT_KEY *\r
6144GetHotKeyFromRegisterList (\r
6145 IN EFI_INPUT_KEY *KeyData\r
6146 )\r
6147{\r
6148 LIST_ENTRY *Link;\r
6149 BROWSER_HOT_KEY *HotKey;\r
6150\r
6151 Link = GetFirstNode (&gBrowserHotKeyList);\r
6152 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
6153 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
6154 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
6155 return HotKey;\r
6156 }\r
6157 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
6158 }\r
6159 \r
6160 return NULL;\r
6161}\r
6162\r
6163/**\r
6164 Configure what scope the hot key will impact.\r
6165 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
6166 If no scope is set, the default scope will be FormSet level.\r
6167 After all registered hot keys are removed, previous Scope can reset to another level.\r
6168 \r
6169 @param[in] Scope Scope level to be set. \r
6170 \r
6171 @retval EFI_SUCCESS Scope is set correctly.\r
6172 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
6173 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
6174\r
6175**/\r
6176EFI_STATUS\r
6177EFIAPI\r
6178SetScope (\r
6179 IN BROWSER_SETTING_SCOPE Scope\r
6180 )\r
6181{\r
6182 if (Scope >= MaxLevel) {\r
6183 return EFI_INVALID_PARAMETER;\r
6184 }\r
7c6c064c 6185\r
48a9d5f7
LG
6186 //\r
6187 // When no hot key registered in system or on the first setting,\r
6188 // Scope can be set.\r
6189 //\r
6190 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
6191 gBrowserSettingScope = Scope;\r
6192 mBrowserScopeFirstSet = FALSE;\r
6193 } else if (Scope != gBrowserSettingScope) {\r
6194 return EFI_UNSUPPORTED;\r
6195 }\r
6196\r
6197 return EFI_SUCCESS;\r
6198}\r
6199\r
6200/**\r
6201 Register the hot key with its browser action, or unregistered the hot key.\r
6202 Only support hot key that is not printable character (control key, function key, etc.).\r
6203 If the action value is zero, the hot key will be unregistered if it has been registered.\r
6204 If the same hot key has been registered, the new action and help string will override the previous ones.\r
6205 \r
6206 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
6207 information for the hot key. Its type is EFI_INPUT_KEY to \r
6208 be supported by all ConsoleIn devices.\r
6209 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
6210 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
6211 @param[in] HelpString Help string that describes the hot key information.\r
6212 Its value may be NULL for the unregistered hot key.\r
6213 \r
6214 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
6215 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
6216 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
6217 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
291422d7 6218 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.\r
48a9d5f7
LG
6219**/\r
6220EFI_STATUS\r
6221EFIAPI\r
6222RegisterHotKey (\r
6223 IN EFI_INPUT_KEY *KeyData,\r
6224 IN UINT32 Action,\r
6225 IN UINT16 DefaultId,\r
6226 IN EFI_STRING HelpString OPTIONAL\r
6227 )\r
6228{\r
6229 BROWSER_HOT_KEY *HotKey;\r
6230\r
6231 //\r
6232 // Check input parameters.\r
6233 //\r
6234 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
6235 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
6236 return EFI_INVALID_PARAMETER;\r
6237 }\r
6238\r
6239 //\r
6240 // Check whether the input KeyData is in BrowserHotKeyList.\r
6241 //\r
6242 HotKey = GetHotKeyFromRegisterList (KeyData);\r
6243 \r
6244 //\r
6245 // Unregister HotKey\r
6246 //\r
6247 if (Action == BROWSER_ACTION_UNREGISTER) {\r
6248 if (HotKey != NULL) {\r
6249 //\r
6250 // The registered HotKey is found. \r
6251 // Remove it from List, and free its resource.\r
6252 //\r
6253 RemoveEntryList (&HotKey->Link);\r
6254 FreePool (HotKey->KeyData);\r
6255 FreePool (HotKey->HelpString);\r
6256 return EFI_SUCCESS;\r
6257 } else {\r
6258 //\r
6259 // The registered HotKey is not found. \r
6260 //\r
6261 return EFI_NOT_FOUND;\r
6262 }\r
6263 }\r
291422d7
ED
6264\r
6265 if (HotKey != NULL) {\r
6266 return EFI_ALREADY_STARTED;\r
6267 }\r
6268\r
48a9d5f7 6269 //\r
291422d7 6270 // Create new Key, and add it into List.\r
48a9d5f7 6271 //\r
291422d7
ED
6272 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
6273 ASSERT (HotKey != NULL);\r
6274 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
6275 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
6276 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
48a9d5f7
LG
6277\r
6278 //\r
6279 // Fill HotKey information.\r
6280 //\r
6281 HotKey->Action = Action;\r
6282 HotKey->DefaultId = DefaultId;\r
6283 if (HotKey->HelpString != NULL) {\r
6284 FreePool (HotKey->HelpString);\r
6285 }\r
6286 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
6287\r
6288 return EFI_SUCCESS;\r
6289}\r
6290\r
6291/**\r
6292 Register Exit handler function. \r
6293 When more than one handler function is registered, the latter one will override the previous one. \r
6294 When NULL handler is specified, the previous Exit handler will be unregistered. \r
6295 \r
6296 @param[in] Handler Pointer to handler function. \r
6297\r
6298**/\r
6299VOID\r
6300EFIAPI\r
6301RegiserExitHandler (\r
6302 IN EXIT_HANDLER Handler\r
6303 )\r
6304{\r
6305 ExitHandlerFunction = Handler;\r
6306 return;\r
6307}\r
6308\r
7c6c064c
ED
6309/**\r
6310 Check whether the browser data has been modified.\r
6311\r
6312 @retval TRUE Browser data is modified.\r
6313 @retval FALSE No browser data is modified.\r
6314\r
6315**/\r
6316BOOLEAN\r
6317EFIAPI\r
6318IsBrowserDataModified (\r
6319 VOID\r
6320 )\r
6321{\r
6322 LIST_ENTRY *Link;\r
6323 FORM_BROWSER_FORMSET *FormSet;\r
6324\r
7c6c064c
ED
6325 switch (gBrowserSettingScope) {\r
6326 case FormLevel:\r
27bace9b
ED
6327 if (gCurrentSelection == NULL) {\r
6328 return FALSE;\r
6329 }\r
7c6c064c
ED
6330 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
6331\r
6332 case FormSetLevel:\r
27bace9b
ED
6333 if (gCurrentSelection == NULL) {\r
6334 return FALSE;\r
6335 }\r
7c6c064c
ED
6336 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
6337\r
6338 case SystemLevel:\r
6339 Link = GetFirstNode (&gBrowserFormSetList);\r
6340 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6341 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
27bace9b
ED
6342 if (!ValidateFormSet(FormSet)) {\r
6343 continue;\r
6344 }\r
6345\r
7c6c064c
ED
6346 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
6347 return TRUE;\r
6348 }\r
6349 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6350 }\r
6351 return FALSE;\r
6352\r
6353 default:\r
6354 return FALSE;\r
6355 }\r
6356}\r
6357\r
6358/**\r
6359 Execute the action requested by the Action parameter.\r
6360\r
6361 @param[in] Action Execute the request action.\r
6362 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
6363\r
6364 @retval EFI_SUCCESS Execute the request action succss.\r
6365 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
6366\r
6367**/\r
6368EFI_STATUS \r
6369EFIAPI\r
6370ExecuteAction (\r
6371 IN UINT32 Action,\r
6372 IN UINT16 DefaultId\r
6373 )\r
6374{\r
27bace9b
ED
6375 EFI_STATUS Status;\r
6376 FORM_BROWSER_FORMSET *FormSet;\r
6377 FORM_BROWSER_FORM *Form;\r
7c6c064c 6378\r
27bace9b 6379 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
7c6c064c
ED
6380 return EFI_NOT_READY;\r
6381 }\r
6382\r
27bace9b
ED
6383 Status = EFI_SUCCESS;\r
6384 FormSet = NULL;\r
6385 Form = NULL;\r
6386 if (gBrowserSettingScope < SystemLevel) {\r
6387 FormSet = gCurrentSelection->FormSet;\r
6388 Form = gCurrentSelection->Form; \r
6389 }\r
7c6c064c
ED
6390\r
6391 //\r
6392 // Executet the discard action.\r
6393 //\r
6394 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
27bace9b 6395 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6396 if (EFI_ERROR (Status)) {\r
6397 return Status;\r
6398 }\r
6399 }\r
6400\r
6401 //\r
6402 // Executet the difault action.\r
6403 //\r
6404 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
787fc2a6 6405 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
7c6c064c
ED
6406 if (EFI_ERROR (Status)) {\r
6407 return Status;\r
6408 }\r
892eccc8 6409 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6410 }\r
6411\r
6412 //\r
6413 // Executet the submit action.\r
6414 //\r
6415 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
27bace9b 6416 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6417 if (EFI_ERROR (Status)) {\r
6418 return Status;\r
6419 }\r
6420 }\r
6421\r
6422 //\r
6423 // Executet the reset action.\r
6424 //\r
6425 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
6426 gResetRequired = TRUE;\r
6427 }\r
6428\r
6429 //\r
6430 // Executet the exit action.\r
6431 //\r
6432 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
27bace9b 6433 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6434 if (gBrowserSettingScope == SystemLevel) {\r
6435 if (ExitHandlerFunction != NULL) {\r
6436 ExitHandlerFunction ();\r
6437 }\r
6438 }\r
6439\r
6440 gExitRequired = TRUE;\r
6441 }\r
6442\r
6443 return Status;\r
6444}\r
6445\r
48a9d5f7
LG
6446/**\r
6447 Create reminder to let user to choose save or discard the changed browser data.\r
6448 Caller can use it to actively check the changed browser data.\r
6449\r
6450 @retval BROWSER_NO_CHANGES No browser data is changed.\r
6451 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
6452 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
27bace9b 6453 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
48a9d5f7
LG
6454\r
6455**/\r
6456UINT32\r
6457EFIAPI\r
6458SaveReminder (\r
6459 VOID\r
6460 )\r
6461{\r
6462 LIST_ENTRY *Link;\r
6463 FORM_BROWSER_FORMSET *FormSet;\r
6464 BOOLEAN IsDataChanged;\r
6465 UINT32 DataSavedAction;\r
27bace9b 6466 UINT32 ConfirmRet;\r
48a9d5f7
LG
6467\r
6468 DataSavedAction = BROWSER_NO_CHANGES;\r
6469 IsDataChanged = FALSE;\r
6470 Link = GetFirstNode (&gBrowserFormSetList);\r
6471 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6472 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
6473 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6474 if (!ValidateFormSet(FormSet)) {\r
6475 continue;\r
6476 }\r
7c6c064c 6477 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
48a9d5f7
LG
6478 IsDataChanged = TRUE;\r
6479 break;\r
6480 }\r
48a9d5f7
LG
6481 }\r
6482 \r
6483 //\r
6484 // No data is changed. No save is required. \r
6485 //\r
6486 if (!IsDataChanged) {\r
6487 return DataSavedAction;\r
6488 }\r
6489 \r
6490 //\r
7c6c064c 6491 // If data is changed, prompt user to save or discard it. \r
48a9d5f7 6492 //\r
48a9d5f7 6493 do {\r
27bace9b 6494 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
48a9d5f7 6495\r
27bace9b 6496 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
7c6c064c 6497 SubmitForm (NULL, NULL, SystemLevel);\r
27bace9b 6498 DataSavedAction = BROWSER_SAVE_CHANGES;\r
7c6c064c 6499 break;\r
27bace9b 6500 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
7c6c064c 6501 DiscardForm (NULL, NULL, SystemLevel);\r
27bace9b
ED
6502 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
6503 break;\r
6504 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
6505 DataSavedAction = BROWSER_KEEP_CURRENT;\r
7c6c064c
ED
6506 break;\r
6507 }\r
6508 } while (1);\r
48a9d5f7
LG
6509\r
6510 return DataSavedAction;\r
6511}\r
7da62bc0
ED
6512\r
6513/**\r
6514 Check whether the Reset Required for the browser\r
6515\r
6516 @retval TRUE Browser required to reset after exit.\r
6517 @retval FALSE Browser not need to reset after exit.\r
6518\r
6519**/\r
6520BOOLEAN\r
6521EFIAPI\r
6522IsResetRequired (\r
6523 VOID\r
6524 )\r
6525{\r
6526 return gResetRequired;\r
6527}\r
6528\r