]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdeModulePkg ResetSystem: Update the comments of ResetSystem()
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
9f4048f7 4Copyright (c) 2007 - 2017, 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
39cde03c 184 if (IsZeroGuid (&MenuList->FormSetGuid)) {\r
7c6c064c
ED
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
2fa0e11d 941 &gEdkiiFormBrowserExProtocolGuid,\r
48a9d5f7
LG
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
9f4048f7
HW
1975 UnicodeValueToStringS (\r
1976 TemString,\r
1977 BufferLen - ((UINTN)TemString - (UINTN)Value),\r
1978 PREFIX_ZERO | RADIX_HEX,\r
1979 *TemName,\r
1980 4\r
1981 );\r
1982 TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)Value)) / sizeof (CHAR16));\r
816a7110
ED
1983 }\r
1984 } else {\r
1985 BufferLen = StorageWidth * 2 + 1;\r
1986 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1987 ASSERT (Value != NULL);\r
1988 //\r
1989 // Convert Buffer to Hex String\r
1990 //\r
1991 TemBuffer = Src + StorageWidth - 1;\r
1992 TemString = Value;\r
1993 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
9f4048f7
HW
1994 UnicodeValueToStringS (\r
1995 TemString,\r
1996 BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)Value),\r
1997 PREFIX_ZERO | RADIX_HEX,\r
1998 *TemBuffer,\r
1999 2\r
2000 );\r
2001 TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)Value) / sizeof (CHAR16));\r
816a7110 2002 }\r
63d55bb9 2003 }\r
7936fb6a 2004\r
7c6c064c 2005 Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
816a7110 2006 FreePool (Value);\r
7c6c064c
ED
2007 if (EFI_ERROR (Status)) {\r
2008 return Status;\r
2009 }\r
816a7110
ED
2010 }\r
2011 } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
7248790e
ED
2012 //\r
2013 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
2014 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
2015 //\r
2016 if (IsBufferStorage) {\r
2017 Length = StrLen (Question->BlockName) + 7;\r
2018 } else {\r
2019 Length = StrLen (Question->VariableName) + 2;\r
2020 }\r
2021 if (!IsBufferStorage && IsString) {\r
2022 Length += (StrLen ((CHAR16 *) Src) * 4);\r
2023 } else {\r
2024 Length += (StorageWidth * 2);\r
2025 }\r
a35ecb75
ED
2026 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
2027 ASSERT (FormsetStorage != NULL);\r
5ad66ec6
DB
2028 MaxLen = StrLen (FormsetStorage->ConfigHdr) + Length + 1;\r
2029 ConfigResp = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7248790e 2030 ASSERT (ConfigResp != NULL);\r
7936fb6a 2031\r
5ad66ec6 2032 StrCpyS (ConfigResp, MaxLen, FormsetStorage->ConfigHdr);\r
7248790e 2033 if (IsBufferStorage) {\r
5ad66ec6
DB
2034 StrCatS (ConfigResp, MaxLen, Question->BlockName);\r
2035 StrCatS (ConfigResp, MaxLen, L"&VALUE=");\r
7248790e 2036 } else {\r
5ad66ec6
DB
2037 StrCatS (ConfigResp, MaxLen, L"&");\r
2038 StrCatS (ConfigResp, MaxLen, Question->VariableName);\r
2039 StrCatS (ConfigResp, MaxLen, L"=");\r
7248790e 2040 }\r
cce6230f 2041\r
7248790e 2042 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 2043\r
7248790e 2044 if (!IsBufferStorage && IsString) {\r
7936fb6a 2045 //\r
7248790e 2046 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
7936fb6a 2047 //\r
7248790e
ED
2048 TemName = (CHAR16 *) Src;\r
2049 TemString = Value;\r
2050 for (; *TemName != L'\0'; TemName++) {\r
9f4048f7
HW
2051 UnicodeValueToStringS (\r
2052 TemString,\r
2053 MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
2054 PREFIX_ZERO | RADIX_HEX,\r
2055 *TemName,\r
2056 4\r
2057 );\r
2058 TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
63d55bb9 2059 }\r
7248790e 2060 } else {\r
63d55bb9 2061 //\r
7248790e 2062 // Convert Buffer to Hex String\r
63d55bb9 2063 //\r
7248790e
ED
2064 TemBuffer = Src + StorageWidth - 1;\r
2065 TemString = Value;\r
2066 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
9f4048f7
HW
2067 UnicodeValueToStringS (\r
2068 TemString,\r
2069 MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
2070 PREFIX_ZERO | RADIX_HEX,\r
2071 *TemBuffer,\r
2072 2\r
2073 );\r
2074 TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
63d55bb9 2075 }\r
7248790e
ED
2076 }\r
2077\r
2078 //\r
2079 // Convert to lower char.\r
2080 //\r
2081 for (TemString = Value; *Value != L'\0'; Value++) {\r
2082 if (*Value >= L'A' && *Value <= L'Z') {\r
2083 *Value = (CHAR16) (*Value - L'A' + L'a');\r
7936fb6a 2084 }\r
2085 }\r
7248790e
ED
2086\r
2087 //\r
2088 // Submit Question Value to Configuration Driver\r
2089 //\r
2090 Status = mHiiConfigRouting->RouteConfig (\r
2091 mHiiConfigRouting,\r
2092 ConfigResp,\r
2093 &Progress\r
2094 );\r
2095 if (EFI_ERROR (Status)) {\r
2096 FreePool (ConfigResp);\r
2097 return Status;\r
2098 }\r
2099 FreePool (ConfigResp);\r
2100 \r
7936fb6a 2101 //\r
cce6230f 2102 // Sync storage, from editbuffer to buffer.\r
7936fb6a 2103 //\r
cce6230f 2104 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
7936fb6a 2105 }\r
2106\r
2107 return Status;\r
2108}\r
2109\r
2110\r
2111/**\r
7c6c064c 2112 Perform nosubmitif check for a Form.\r
7936fb6a 2113\r
2114 @param FormSet FormSet data structure.\r
2115 @param Form Form data structure.\r
2116 @param Question The Question to be validated.\r
7c6c064c 2117 @param Type Validation type: NoSubmit\r
7936fb6a 2118\r
2119 @retval EFI_SUCCESS Form validation pass.\r
2120 @retval other Form validation failed.\r
2121\r
2122**/\r
2123EFI_STATUS\r
2124ValidateQuestion (\r
2125 IN FORM_BROWSER_FORMSET *FormSet,\r
2126 IN FORM_BROWSER_FORM *Form,\r
2127 IN FORM_BROWSER_STATEMENT *Question,\r
2128 IN UINTN Type\r
2129 )\r
2130{\r
2131 EFI_STATUS Status;\r
2132 LIST_ENTRY *Link;\r
2133 LIST_ENTRY *ListHead;\r
7936fb6a 2134 FORM_EXPRESSION *Expression;\r
bfae1330
ED
2135 UINT32 BrowserStatus;\r
2136 CHAR16 *ErrorStr;\r
2137\r
2138 BrowserStatus = BROWSER_SUCCESS;\r
2139 ErrorStr = NULL;\r
2140\r
2141 switch (Type) {\r
2142 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2143 ListHead = &Question->InconsistentListHead;\r
2144 break;\r
7936fb6a 2145\r
bfae1330
ED
2146 case EFI_HII_EXPRESSION_WARNING_IF:\r
2147 ListHead = &Question->WarningListHead;\r
2148 break;\r
2149\r
2150 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
7936fb6a 2151 ListHead = &Question->NoSubmitListHead;\r
bfae1330
ED
2152 break;\r
2153\r
2154 default:\r
2155 ASSERT (FALSE);\r
7936fb6a 2156 return EFI_UNSUPPORTED;\r
2157 }\r
2158\r
2159 Link = GetFirstNode (ListHead);\r
2160 while (!IsNull (ListHead, Link)) {\r
2161 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
2162\r
2163 //\r
2164 // Evaluate the expression\r
2165 //\r
2166 Status = EvaluateExpression (FormSet, Form, Expression);\r
2167 if (EFI_ERROR (Status)) {\r
2168 return Status;\r
2169 }\r
2170\r
e6106e89 2171 if (IsTrue (&Expression->Result)) {\r
bfae1330
ED
2172 switch (Type) {\r
2173 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2174 BrowserStatus = BROWSER_INCONSISTENT_IF;\r
2175 break;\r
2176\r
2177 case EFI_HII_EXPRESSION_WARNING_IF:\r
2178 BrowserStatus = BROWSER_WARNING_IF;\r
2179 break;\r
2180\r
2181 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
2182 BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
2183 //\r
2184 // This code only used to compatible with old display engine,\r
2185 // New display engine will not use this field.\r
2186 //\r
2187 if (Expression->Error != 0) {\r
2188 ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
7c6c064c 2189 }\r
bfae1330
ED
2190 break;\r
2191\r
2192 default:\r
2193 ASSERT (FALSE);\r
2194 break;\r
7936fb6a 2195 }\r
2196\r
4d4deaac
ED
2197 if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
2198 //\r
2199 // If in system submit process and for no_submit_if check, not popup this error message.\r
2200 // Will process this fail again later in not system submit process.\r
2201 //\r
2202 PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
2203 }\r
bfae1330
ED
2204\r
2205 if (ErrorStr != NULL) {\r
2206 FreePool (ErrorStr);\r
2207 }\r
2208\r
2209 if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
2210 return EFI_SUCCESS;\r
2211 } else {\r
2212 return EFI_NOT_READY;\r
2213 }\r
7936fb6a 2214 }\r
2215\r
2216 Link = GetNextNode (ListHead, Link);\r
2217 }\r
2218\r
2219 return EFI_SUCCESS;\r
2220}\r
2221\r
bfae1330
ED
2222/**\r
2223 Perform question check. \r
2224 \r
2225 If one question has more than one check, process form high priority to low. \r
2226 Only one error info will be popup.\r
2227\r
2228 @param FormSet FormSet data structure.\r
2229 @param Form Form data structure.\r
2230 @param Question The Question to be validated.\r
2231\r
2232 @retval EFI_SUCCESS Form validation pass.\r
2233 @retval other Form validation failed.\r
2234\r
2235**/\r
2236EFI_STATUS\r
2237ValueChangedValidation (\r
2238 IN FORM_BROWSER_FORMSET *FormSet,\r
2239 IN FORM_BROWSER_FORM *Form,\r
2240 IN FORM_BROWSER_STATEMENT *Question\r
2241 )\r
2242{\r
2243 EFI_STATUS Status;\r
2244\r
2245 Status = EFI_SUCCESS;\r
2246\r
2247 //\r
2248 // Do the inconsistentif check.\r
2249 //\r
2250 if (!IsListEmpty (&Question->InconsistentListHead)) {\r
2251 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
2252 if (EFI_ERROR (Status)) {\r
2253 return Status;\r
2254 }\r
2255 }\r
2256\r
2257 //\r
2258 // Do the warningif check.\r
2259 //\r
2260 if (!IsListEmpty (&Question->WarningListHead)) {\r
2261 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
2262 }\r
2263\r
2264 return Status;\r
2265}\r
7936fb6a 2266\r
2267/**\r
5adb8db7 2268 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 2269\r
2270 @param FormSet FormSet data structure.\r
b18e7050 2271 @param CurrentForm Current input form data structure.\r
4d4deaac 2272 @param Statement The statement for this check.\r
7936fb6a 2273\r
2274 @retval EFI_SUCCESS Form validation pass.\r
2275 @retval other Form validation failed.\r
2276\r
2277**/\r
2278EFI_STATUS\r
2279NoSubmitCheck (\r
4d4deaac
ED
2280 IN FORM_BROWSER_FORMSET *FormSet,\r
2281 IN OUT FORM_BROWSER_FORM **CurrentForm,\r
2282 OUT FORM_BROWSER_STATEMENT **Statement\r
7936fb6a 2283 )\r
2284{\r
2285 EFI_STATUS Status;\r
2286 LIST_ENTRY *Link;\r
2287 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
2288 FORM_BROWSER_FORM *Form;\r
2289 LIST_ENTRY *LinkForm;\r
7936fb6a 2290\r
5adb8db7
LG
2291 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
2292 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
2293 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
2294 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
2295\r
4d4deaac 2296 if (*CurrentForm != NULL && *CurrentForm != Form) {\r
b18e7050
ED
2297 continue;\r
2298 }\r
7936fb6a 2299\r
5adb8db7
LG
2300 Link = GetFirstNode (&Form->StatementListHead);\r
2301 while (!IsNull (&Form->StatementListHead, Link)) {\r
2302 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
5adb8db7
LG
2303 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2304 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
2305 if (*CurrentForm == NULL) {\r
2306 *CurrentForm = Form;\r
2307 }\r
2308 if (Statement != NULL) {\r
2309 *Statement = Question;\r
2310 }\r
5adb8db7
LG
2311 return Status;\r
2312 }\r
2313\r
2314 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 2315 }\r
7936fb6a 2316 }\r
2317\r
2318 return EFI_SUCCESS;\r
2319}\r
2320\r
7936fb6a 2321/**\r
b18e7050
ED
2322 Fill storage's edit copy with settings requested from Configuration Driver.\r
2323\r
7c6c064c
ED
2324 @param Storage The storage which need to sync.\r
2325 @param ConfigRequest The config request string which used to sync storage.\r
cce6230f
ED
2326 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2327 editbuffer to buffer\r
2328 if TRUE, copy the editbuffer to the buffer.\r
2329 if FALSE, copy the buffer to the editbuffer.\r
b18e7050
ED
2330\r
2331 @retval EFI_SUCCESS The function completed successfully.\r
2332\r
2333**/\r
2334EFI_STATUS\r
7c6c064c 2335SynchronizeStorage (\r
7c6c064c
ED
2336 OUT BROWSER_STORAGE *Storage,\r
2337 IN CHAR16 *ConfigRequest,\r
2338 IN BOOLEAN SyncOrRestore\r
b18e7050
ED
2339 )\r
2340{\r
2341 EFI_STATUS Status;\r
2342 EFI_STRING Progress;\r
2343 EFI_STRING Result;\r
2344 UINTN BufferSize;\r
2345 LIST_ENTRY *Link;\r
2346 NAME_VALUE_NODE *Node;\r
cce6230f
ED
2347 UINT8 *Src;\r
2348 UINT8 *Dst;\r
b18e7050
ED
2349\r
2350 Status = EFI_SUCCESS;\r
2351 Result = NULL;\r
25361615 2352\r
7c6c064c
ED
2353 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2354 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
2355 BufferSize = Storage->Size;\r
cce6230f
ED
2356\r
2357 if (SyncOrRestore) {\r
7c6c064c
ED
2358 Src = Storage->EditBuffer;\r
2359 Dst = Storage->Buffer;\r
cce6230f 2360 } else {\r
7c6c064c
ED
2361 Src = Storage->Buffer;\r
2362 Dst = Storage->EditBuffer;\r
cce6230f
ED
2363 }\r
2364\r
7c6c064c
ED
2365 if (ConfigRequest != NULL) {\r
2366 Status = mHiiConfigRouting->BlockToConfig(\r
2367 mHiiConfigRouting,\r
2368 ConfigRequest,\r
2369 Src,\r
2370 BufferSize,\r
2371 &Result,\r
2372 &Progress\r
2373 );\r
2374 if (EFI_ERROR (Status)) {\r
2375 return Status;\r
2376 }\r
b18e7050 2377\r
7c6c064c
ED
2378 Status = mHiiConfigRouting->ConfigToBlock (\r
2379 mHiiConfigRouting,\r
2380 Result,\r
2381 Dst,\r
2382 &BufferSize,\r
2383 &Progress\r
2384 );\r
2385 if (Result != NULL) {\r
2386 FreePool (Result);\r
2387 }\r
2388 } else {\r
2389 CopyMem (Dst, Src, BufferSize);\r
b18e7050 2390 }\r
7c6c064c
ED
2391 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2392 Link = GetFirstNode (&Storage->NameValueListHead);\r
2393 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
b18e7050
ED
2394 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2395\r
7c6c064c
ED
2396 if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
2397 (ConfigRequest == NULL)) {\r
cce6230f
ED
2398 if (SyncOrRestore) {\r
2399 NewStringCpy (&Node->Value, Node->EditValue);\r
2400 } else {\r
2401 NewStringCpy (&Node->EditValue, Node->Value);\r
b18e7050 2402 }\r
b18e7050
ED
2403 }\r
2404\r
7c6c064c 2405 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
b18e7050
ED
2406 }\r
2407 }\r
2408\r
2409 return Status;\r
2410}\r
2411\r
816a7110
ED
2412/**\r
2413 When discard the question value, call the callback function with Changed type\r
2414 to inform the hii driver.\r
2415\r
2416 @param FormSet FormSet data structure.\r
2417 @param Form Form data structure.\r
2418\r
2419**/\r
2420VOID\r
2421SendDiscardInfoToDriver (\r
2422 IN FORM_BROWSER_FORMSET *FormSet,\r
2423 IN FORM_BROWSER_FORM *Form\r
2424 )\r
2425{\r
2426 LIST_ENTRY *Link;\r
2427 FORM_BROWSER_STATEMENT *Question;\r
816a7110
ED
2428 EFI_IFR_TYPE_VALUE *TypeValue;\r
2429 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2430\r
70f1d5e7
ED
2431 if (FormSet->ConfigAccess == NULL) {\r
2432 return;\r
2433 }\r
2434\r
816a7110
ED
2435 Link = GetFirstNode (&Form->StatementListHead);\r
2436 while (!IsNull (&Form->StatementListHead, Link)) {\r
2437 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2438 Link = GetNextNode (&Form->StatementListHead, Link);\r
2439\r
2440 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2441 continue;\r
2442 }\r
2443\r
e213ae45
ED
2444 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2445 continue;\r
2446 }\r
2447\r
816a7110
ED
2448 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2449 continue;\r
2450 }\r
2451\r
7c6c064c 2452 if (!Question->ValueChanged) {\r
816a7110
ED
2453 continue;\r
2454 }\r
2455\r
737adca3
ED
2456 //\r
2457 // Restore the question value before call the CHANGED callback type.\r
2458 //\r
2459 GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
2460\r
cb312fb1
DB
2461 if (Question->Operand == EFI_IFR_STRING_OP){\r
2462 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
2463 }\r
2464\r
816a7110
ED
2465 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2466 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2467 } else {\r
2468 TypeValue = &Question->HiiValue.Value;\r
2469 }\r
2470\r
2471 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2472 FormSet->ConfigAccess->Callback (\r
2473 FormSet->ConfigAccess,\r
2474 EFI_BROWSER_ACTION_CHANGED,\r
2475 Question->QuestionId,\r
2476 Question->HiiValue.Type,\r
2477 TypeValue,\r
2478 &ActionRequest\r
2479 );\r
2480 }\r
2481}\r
b18e7050 2482\r
3cb44c20
DB
2483/**\r
2484 When submit the question value, call the callback function with Submitted type\r
2485 to inform the hii driver.\r
2486\r
2487 @param FormSet FormSet data structure.\r
2488 @param Form Form data structure.\r
2489\r
2490**/\r
2491VOID\r
2492SubmitCallbackForForm (\r
2493 IN FORM_BROWSER_FORMSET *FormSet,\r
2494 IN FORM_BROWSER_FORM *Form\r
2495 )\r
2496{\r
2497 LIST_ENTRY *Link;\r
2498 FORM_BROWSER_STATEMENT *Question;\r
2499 EFI_IFR_TYPE_VALUE *TypeValue;\r
2500 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2501\r
2502 if (FormSet->ConfigAccess == NULL) {\r
2503 return;\r
2504 }\r
2505\r
2506 Link = GetFirstNode (&Form->StatementListHead);\r
2507 while (!IsNull (&Form->StatementListHead, Link)) {\r
2508 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2509 Link = GetNextNode (&Form->StatementListHead, Link);\r
2510\r
2511 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2512 continue;\r
2513 }\r
2514\r
2515 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2516 continue;\r
2517 }\r
2518\r
2519 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2520 continue;\r
2521 }\r
2522\r
2523 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2524 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2525 } else {\r
2526 TypeValue = &Question->HiiValue.Value;\r
2527 }\r
2528\r
2529 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2530 FormSet->ConfigAccess->Callback (\r
2531 FormSet->ConfigAccess,\r
2532 EFI_BROWSER_ACTION_SUBMITTED,\r
2533 Question->QuestionId,\r
2534 Question->HiiValue.Type,\r
2535 TypeValue,\r
2536 &ActionRequest\r
2537 );\r
2538 }\r
2539}\r
2540\r
2541/**\r
2542 When value set Success, call the submit callback function.\r
2543\r
2544 @param FormSet FormSet data structure.\r
2545 @param Form Form data structure.\r
2546\r
2547**/\r
2548VOID\r
2549SubmitCallback (\r
2550 IN FORM_BROWSER_FORMSET *FormSet,\r
2551 IN FORM_BROWSER_FORM *Form\r
2552 )\r
2553{\r
2554 FORM_BROWSER_FORM *CurrentForm;\r
2555 LIST_ENTRY *Link;\r
2556\r
2557 if (Form != NULL) {\r
2558 SubmitCallbackForForm(FormSet, Form);\r
2559 return;\r
2560 }\r
2561\r
2562 Link = GetFirstNode (&FormSet->FormListHead);\r
2563 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2564 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2565 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2566\r
2567 SubmitCallbackForForm(FormSet, CurrentForm);\r
2568 }\r
2569}\r
2570\r
938baa1f 2571/**\r
dcca25d1 2572 Validate the HiiHandle.\r
938baa1f 2573\r
dcca25d1 2574 @param HiiHandle The input HiiHandle which need to validate.\r
938baa1f
ED
2575\r
2576 @retval TRUE The handle is validate.\r
2577 @retval FALSE The handle is invalidate.\r
2578\r
2579**/\r
2580BOOLEAN\r
93551a01
ED
2581ValidateHiiHandle (\r
2582 EFI_HII_HANDLE HiiHandle\r
938baa1f
ED
2583 )\r
2584{\r
2585 EFI_HII_HANDLE *HiiHandles;\r
2586 UINTN Index;\r
2587 BOOLEAN Find;\r
2588\r
93551a01
ED
2589 if (HiiHandle == NULL) {\r
2590 return FALSE;\r
2591 }\r
2592\r
938baa1f 2593 Find = FALSE;\r
93551a01 2594\r
938baa1f
ED
2595 HiiHandles = HiiGetHiiHandles (NULL);\r
2596 ASSERT (HiiHandles != NULL);\r
2597\r
938baa1f 2598 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
93551a01 2599 if (HiiHandles[Index] == HiiHandle) {\r
938baa1f
ED
2600 Find = TRUE;\r
2601 break;\r
2602 }\r
2603 }\r
2604\r
93551a01
ED
2605 FreePool (HiiHandles);\r
2606\r
2607 return Find;\r
2608}\r
2609\r
2610/**\r
2611 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2612\r
2613 @param FormSet The input FormSet which need to validate.\r
2614\r
2615 @retval TRUE The handle is validate.\r
2616 @retval FALSE The handle is invalidate.\r
2617\r
2618**/\r
2619BOOLEAN\r
2620ValidateFormSet (\r
2621 FORM_BROWSER_FORMSET *FormSet\r
2622 )\r
2623{\r
2624 BOOLEAN Find;\r
2625\r
2626 ASSERT (FormSet != NULL);\r
2627\r
2628 Find = ValidateHiiHandle(FormSet->HiiHandle);\r
275ea01e
ED
2629 //\r
2630 // Should not remove the formset which is being used.\r
2631 //\r
2632 if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
0a6f8af5 2633 CleanBrowserStorage(FormSet);\r
938baa1f
ED
2634 RemoveEntryList (&FormSet->Link);\r
2635 DestroyFormSet (FormSet);\r
2636 }\r
2637\r
938baa1f
ED
2638 return Find;\r
2639}\r
7c6c064c
ED
2640/**\r
2641 Check whether need to enable the reset flag in form level.\r
2642 Also clean all ValueChanged flag in question.\r
2643\r
2644 @param SetFlag Whether need to set the Reset Flag.\r
4d4deaac 2645 @param FormSet FormSet data structure.\r
7c6c064c
ED
2646 @param Form Form data structure.\r
2647\r
2648**/\r
2649VOID\r
2650UpdateFlagForForm (\r
2651 IN BOOLEAN SetFlag,\r
4d4deaac 2652 IN FORM_BROWSER_FORMSET *FormSet,\r
7c6c064c
ED
2653 IN FORM_BROWSER_FORM *Form\r
2654 )\r
2655{\r
2656 LIST_ENTRY *Link;\r
2657 FORM_BROWSER_STATEMENT *Question;\r
4d4deaac 2658 BOOLEAN OldValue;\r
7c6c064c 2659\r
7c6c064c
ED
2660 Link = GetFirstNode (&Form->StatementListHead);\r
2661 while (!IsNull (&Form->StatementListHead, Link)) {\r
2662 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4d4deaac 2663 Link = GetNextNode (&Form->StatementListHead, Link);\r
7c6c064c 2664\r
4d4deaac
ED
2665 if (!Question->ValueChanged) {\r
2666 continue;\r
7c6c064c 2667 }\r
4d4deaac
ED
2668\r
2669 OldValue = Question->ValueChanged;\r
2670\r
2671 //\r
2672 // Compare the buffer and editbuffer data to see whether the data has been saved.\r
2673 //\r
2674 Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
2675\r
2676 //\r
2677 // Only the changed data has been saved, then need to set the reset flag.\r
2678 //\r
f2e7732e
ED
2679 if (SetFlag && OldValue && !Question->ValueChanged) {\r
2680 if ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
2681 gResetRequired = TRUE;\r
2682 }\r
2683\r
2684 if ((Question->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
2685 gFlagReconnect = TRUE;\r
2686 }\r
4d4deaac 2687 } \r
7c6c064c
ED
2688 }\r
2689}\r
2690\r
2691/**\r
2692 Check whether need to enable the reset flag.\r
2693 Also clean ValueChanged flag for all statements.\r
2694\r
2695 Form level or formset level, only one.\r
2696 \r
2697 @param SetFlag Whether need to set the Reset Flag.\r
2698 @param FormSet FormSet data structure.\r
2699 @param Form Form data structure.\r
2700\r
2701**/\r
2702VOID\r
2703ValueChangeResetFlagUpdate (\r
2704 IN BOOLEAN SetFlag,\r
2705 IN FORM_BROWSER_FORMSET *FormSet,\r
2706 IN FORM_BROWSER_FORM *Form \r
2707 )\r
2708{\r
2709 FORM_BROWSER_FORM *CurrentForm;\r
2710 LIST_ENTRY *Link;\r
2711\r
7c6c064c 2712 if (Form != NULL) {\r
4d4deaac 2713 UpdateFlagForForm(SetFlag, FormSet, Form);\r
7c6c064c
ED
2714 return;\r
2715 }\r
2716\r
2717 Link = GetFirstNode (&FormSet->FormListHead);\r
2718 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2719 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2720 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2721\r
4d4deaac 2722 UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
7c6c064c
ED
2723 }\r
2724}\r
938baa1f 2725\r
4d4deaac
ED
2726/**\r
2727 Base on the return Progress string to find the form. \r
2728 \r
2729 Base on the first return Offset/Width (Name) string to find the form\r
2730 which keep this string.\r
2731\r
2732 @param FormSet FormSet data structure.\r
2733 @param Storage Storage which has this Progress string.\r
2734 @param Progress The Progress string which has the first fail string.\r
2735 @param RetForm The return form for this progress string.\r
2736 @param RetQuestion The return question for the error progress string.\r
2737\r
2738 @retval TRUE Find the error form and statement for this error progress string.\r
2739 @retval FALSE Not find the error form.\r
2740\r
2741**/\r
2742BOOLEAN\r
2743FindQuestionFromProgress (\r
2744 IN FORM_BROWSER_FORMSET *FormSet,\r
2745 IN BROWSER_STORAGE *Storage,\r
2746 IN EFI_STRING Progress,\r
2747 OUT FORM_BROWSER_FORM **RetForm,\r
2748 OUT FORM_BROWSER_STATEMENT **RetQuestion\r
2749 )\r
2750{\r
2751 LIST_ENTRY *Link;\r
2752 LIST_ENTRY *LinkStorage;\r
2753 LIST_ENTRY *LinkStatement;\r
2754 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2755 FORM_BROWSER_FORM *Form;\r
2756 EFI_STRING EndStr;\r
2757 FORM_BROWSER_STATEMENT *Statement;\r
2758\r
2759 ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
2760\r
2761 ConfigInfo = NULL;\r
2762 *RetForm = NULL;\r
2763 *RetQuestion = NULL;\r
2764\r
2765 //\r
2766 // Skip the first "&" or the ConfigHdr part.\r
2767 //\r
2768 if (*Progress == '&') {\r
2769 Progress++;\r
2770 } else {\r
2771 //\r
2772 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2773 //\r
2774 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2775 //\r
2776 // For Name/Value type, Skip the ConfigHdr part.\r
2777 //\r
2778 EndStr = StrStr (Progress, L"PATH=");\r
e77d2f9d 2779 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2780 while (*EndStr != '&') {\r
2781 EndStr++;\r
2782 }\r
2783\r
2784 *EndStr = '\0';\r
2785 } else {\r
2786 //\r
2787 // For Buffer type, Skip the ConfigHdr part.\r
2788 //\r
2789 EndStr = StrStr (Progress, L"&OFFSET=");\r
e77d2f9d 2790 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2791 *EndStr = '\0';\r
2792 }\r
2793\r
2794 Progress = EndStr + 1;\r
2795 }\r
2796\r
2797 //\r
2798 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2799 //\r
2800 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2801 //\r
2802 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2803 // here, just keep the "Fred" string.\r
2804 //\r
2805 EndStr = StrStr (Progress, L"=");\r
e77d2f9d 2806 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2807 *EndStr = '\0';\r
2808 } else {\r
2809 //\r
2810 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2811 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2812 //\r
2813 EndStr = StrStr (Progress, L"&VALUE=");\r
e77d2f9d 2814 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2815 *EndStr = '\0';\r
2816 }\r
2817\r
2818 //\r
2819 // Search in the form list.\r
2820 //\r
2821 Link = GetFirstNode (&FormSet->FormListHead);\r
2822 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2823 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2824 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2825\r
2826 //\r
2827 // Search in the ConfigReqeust list in this form.\r
2828 //\r
2829 LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
2830 while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
2831 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
2832 LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
2833\r
2834 if (Storage != ConfigInfo->Storage) {\r
2835 continue;\r
2836 }\r
2837\r
2838 if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
2839 //\r
2840 // Find the OffsetWidth string in this form.\r
2841 //\r
2842 *RetForm = Form;\r
2843 break;\r
2844 }\r
2845 }\r
2846\r
2847 if (*RetForm != NULL) {\r
2848 LinkStatement = GetFirstNode (&Form->StatementListHead);\r
2849 while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
2850 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
2851 LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
2852\r
2853 if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
2854 *RetQuestion = Statement;\r
2855 break;\r
2856 }\r
a35ecb75
ED
2857\r
2858 if (Statement->VariableName != NULL && StrStr (Statement->VariableName, Progress) != NULL) {\r
2859 *RetQuestion = Statement;\r
2860 break;\r
2861 }\r
4d4deaac
ED
2862 }\r
2863 }\r
2864\r
2865 if (*RetForm != NULL) {\r
2866 break;\r
2867 }\r
2868 }\r
2869\r
2870 //\r
2871 // restore the OffsetWidth string to the original format.\r
2872 //\r
2873 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2874 *EndStr = '=';\r
2875 } else {\r
2876 *EndStr = '&';\r
2877 }\r
2878\r
5039b444 2879 return (BOOLEAN) (*RetForm != NULL);\r
4d4deaac
ED
2880}\r
2881\r
8066b27e
DB
2882/**\r
2883 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest\r
2884 for form and formset.\r
2885\r
2886 @param Storage Storage which has this Progress string.\r
2887 @param ConfigRequest The ConfigRequest string.\r
2888 @param Progress The Progress string which has the first fail string.\r
2889 @param RestoreConfigRequest Return the RestoreConfigRequest string.\r
2890 @param SyncConfigRequest Return the SyncConfigRequest string.\r
2891\r
2892**/\r
2893VOID\r
2894GetSyncRestoreConfigRequest(\r
2895 IN BROWSER_STORAGE *Storage,\r
2896 IN EFI_STRING ConfigRequest,\r
2897 IN EFI_STRING Progress,\r
2898 OUT EFI_STRING *RestoreConfigRequest,\r
2899 OUT EFI_STRING *SyncConfigRequest\r
2900 )\r
2901{\r
2902 EFI_STRING EndStr;\r
2903 EFI_STRING ConfigHdrEndStr;\r
2904 EFI_STRING ElementStr;\r
2905 UINTN TotalSize;\r
2906 UINTN RestoreEleSize;\r
2907 UINTN SyncSize;\r
2908\r
2909 ASSERT ((*Progress == L'&') || (*Progress == L'G'));\r
2910 //\r
2911 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.\r
2912 // Need to restore all the fields in the ConfigRequest.\r
2913 //\r
2914 if (*Progress == L'G') {\r
2915 *RestoreConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
2916 ASSERT (*RestoreConfigRequest != NULL);\r
2917 return;\r
2918 }\r
2919\r
2920 //\r
2921 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2922 //\r
2923 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2924 //\r
2925 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2926 // here, just keep the "Fred" string.\r
2927 //\r
2928 EndStr = StrStr (Progress, L"=");\r
2929 ASSERT (EndStr != NULL);\r
2930 *EndStr = L'\0';\r
2931 //\r
2932 // Find the ConfigHdr in ConfigRequest.\r
2933 //\r
2934 ConfigHdrEndStr = StrStr (ConfigRequest, L"PATH=");\r
2935 ASSERT (ConfigHdrEndStr != NULL);\r
2936 while (*ConfigHdrEndStr != L'&') {\r
2937 ConfigHdrEndStr++;\r
2938 }\r
2939 } else {\r
2940 //\r
2941 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2942 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2943 //\r
2944 EndStr = StrStr (Progress, L"&VALUE=");\r
2945 ASSERT (EndStr != NULL);\r
2946 *EndStr = L'\0';\r
2947 //\r
2948 // Find the ConfigHdr in ConfigRequest.\r
2949 //\r
2950 ConfigHdrEndStr = StrStr (ConfigRequest, L"&OFFSET=");\r
2951 }\r
2952 //\r
2953 // Find the first fail pair in the ConfigRequest.\r
2954 //\r
2955 ElementStr = StrStr (ConfigRequest, Progress);\r
2956 ASSERT (ElementStr != NULL);\r
2957 //\r
2958 // To get the RestoreConfigRequest.\r
2959 //\r
2960 RestoreEleSize = StrSize (ElementStr);\r
2961 TotalSize = (ConfigHdrEndStr - ConfigRequest) * sizeof (CHAR16) + RestoreEleSize + sizeof (CHAR16);\r
2962 *RestoreConfigRequest = AllocateZeroPool (TotalSize);\r
2963 ASSERT (*RestoreConfigRequest != NULL);\r
2964 StrnCpyS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ConfigRequest, ConfigHdrEndStr - ConfigRequest);\r
2965 StrCatS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ElementStr);\r
2966 //\r
2967 // To get the SyncConfigRequest.\r
2968 //\r
2969 SyncSize = StrSize (ConfigRequest) - RestoreEleSize + sizeof (CHAR16);\r
2970 *SyncConfigRequest = AllocateZeroPool (SyncSize);\r
2971 ASSERT (*SyncConfigRequest != NULL);\r
2972 StrnCpyS (*SyncConfigRequest, SyncSize / sizeof (CHAR16), ConfigRequest, SyncSize / sizeof (CHAR16) - 1);\r
2973\r
2974 //\r
2975 // restore the Progress string to the original format.\r
2976 //\r
2977 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2978 *EndStr = L'=';\r
2979 } else {\r
2980 *EndStr = L'&';\r
2981 }\r
2982}\r
2983\r
4d4deaac
ED
2984/**\r
2985 Popup an save error info and get user input.\r
2986\r
2987 @param TitleId The form title id.\r
2988 @param HiiHandle The hii handle for this package.\r
2989\r
2990 @retval UINT32 The user select option for the save fail.\r
2991 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2992**/\r
2993UINT32\r
2994ConfirmSaveFail (\r
2995 IN EFI_STRING_ID TitleId,\r
2996 IN EFI_HII_HANDLE HiiHandle\r
2997 )\r
2998{\r
2999 CHAR16 *FormTitle;\r
3000 CHAR16 *StringBuffer;\r
3001 UINT32 RetVal;\r
3002\r
3003 FormTitle = GetToken (TitleId, HiiHandle);\r
3004\r
3005 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
3006 ASSERT (StringBuffer != NULL);\r
3007\r
3008 UnicodeSPrint (\r
3009 StringBuffer, \r
3010 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
3011 L"Submit Fail For Form: %s.", \r
3012 FormTitle\r
3013 );\r
3014\r
3015 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
3016\r
3017 FreePool (StringBuffer);\r
3018 FreePool (FormTitle);\r
3019\r
3020 return RetVal;\r
3021}\r
3022\r
3023/**\r
3024 Popup an NO_SUBMIT_IF error info and get user input.\r
3025\r
3026 @param TitleId The form title id.\r
3027 @param HiiHandle The hii handle for this package.\r
3028\r
3029 @retval UINT32 The user select option for the save fail.\r
3030 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
3031**/\r
3032UINT32\r
3033ConfirmNoSubmitFail (\r
3034 IN EFI_STRING_ID TitleId,\r
3035 IN EFI_HII_HANDLE HiiHandle\r
3036 )\r
3037{\r
3038 CHAR16 *FormTitle;\r
3039 CHAR16 *StringBuffer;\r
3040 UINT32 RetVal;\r
3041\r
3042 FormTitle = GetToken (TitleId, HiiHandle);\r
3043\r
3044 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
3045 ASSERT (StringBuffer != NULL);\r
3046\r
3047 UnicodeSPrint (\r
3048 StringBuffer, \r
3049 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
3050 L"NO_SUBMIT_IF error For Form: %s.", \r
3051 FormTitle\r
3052 );\r
3053\r
3054 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
3055\r
3056 FreePool (StringBuffer);\r
3057 FreePool (FormTitle);\r
3058\r
3059 return RetVal;\r
3060}\r
3061\r
b18e7050 3062/**\r
48a9d5f7 3063 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 3064\r
3065 @param FormSet FormSet data structure.\r
3066 @param Form Form data structure.\r
48a9d5f7 3067 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
3068\r
3069 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3070 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
3071\r
3072**/\r
3073EFI_STATUS\r
3074DiscardForm (\r
3075 IN FORM_BROWSER_FORMSET *FormSet,\r
3076 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 3077 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
3078 )\r
3079{\r
48a9d5f7
LG
3080 LIST_ENTRY *Link;\r
3081 FORMSET_STORAGE *Storage;\r
b18e7050 3082 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
6e74560f
ED
3083 FORM_BROWSER_FORMSET *LocalFormSet;\r
3084 FORM_BROWSER_FORMSET *OldFormSet;\r
b18e7050 3085\r
48a9d5f7
LG
3086 //\r
3087 // Check the supported setting level.\r
3088 //\r
3089 if (SettingScope >= MaxLevel) {\r
3090 return EFI_UNSUPPORTED;\r
3091 }\r
b18e7050 3092\r
7c6c064c 3093 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
48a9d5f7
LG
3094 ConfigInfo = NULL;\r
3095 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3096 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3097 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3098 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 3099\r
48a9d5f7
LG
3100 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3101 continue;\r
3102 }\r
3103\r
3104 //\r
3105 // Skip if there is no RequestElement\r
3106 //\r
3107 if (ConfigInfo->ElementCount == 0) {\r
3108 continue;\r
b18e7050
ED
3109 }\r
3110\r
48a9d5f7
LG
3111 //\r
3112 // Prepare <ConfigResp>\r
3113 //\r
4d4deaac 3114 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
816a7110 3115\r
816a7110
ED
3116 //\r
3117 // Call callback with Changed type to inform the driver.\r
3118 //\r
3119 SendDiscardInfoToDriver (FormSet, Form);\r
3120 }\r
3121\r
4d4deaac 3122 ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
7c6c064c 3123 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
f1660263 3124\r
48a9d5f7
LG
3125 //\r
3126 // Discard Buffer storage or Name/Value storage\r
3127 //\r
3128 Link = GetFirstNode (&FormSet->StorageListHead);\r
3129 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3130 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3131 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3132\r
94f3aae7 3133 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
48a9d5f7
LG
3134 continue;\r
3135 }\r
3136\r
b18e7050 3137 //\r
48a9d5f7 3138 // Skip if there is no RequestElement\r
b18e7050 3139 //\r
48a9d5f7
LG
3140 if (Storage->ElementCount == 0) {\r
3141 continue;\r
3142 }\r
b18e7050 3143\r
4d4deaac 3144 SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
48a9d5f7 3145 }\r
f1660263
ED
3146\r
3147 Link = GetFirstNode (&FormSet->FormListHead);\r
3148 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3149 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3150 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3151 \r
3152 //\r
3153 // Call callback with Changed type to inform the driver.\r
3154 //\r
3155 SendDiscardInfoToDriver (FormSet, Form);\r
3156 }\r
b18e7050 3157\r
7c6c064c 3158 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
48a9d5f7
LG
3159 } else if (SettingScope == SystemLevel) {\r
3160 //\r
3161 // System Level Discard.\r
3162 //\r
6e74560f
ED
3163 OldFormSet = mSystemLevelFormSet;\r
3164\r
48a9d5f7
LG
3165 //\r
3166 // Discard changed value for each FormSet in the maintain list.\r
3167 //\r
3168 Link = GetFirstNode (&gBrowserFormSetList);\r
3169 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3170 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 3171 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
3172 if (!ValidateFormSet(LocalFormSet)) {\r
3173 continue;\r
3174 }\r
6e74560f
ED
3175\r
3176 mSystemLevelFormSet = LocalFormSet;\r
3177\r
938baa1f 3178 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7 3179 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 3180 //\r
48a9d5f7 3181 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 3182 //\r
0a6f8af5 3183 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
3184 RemoveEntryList (&LocalFormSet->Link);\r
3185 DestroyFormSet (LocalFormSet);\r
b18e7050 3186 }\r
b18e7050 3187 }\r
6e74560f
ED
3188\r
3189 mSystemLevelFormSet = OldFormSet;\r
b18e7050
ED
3190 }\r
3191\r
3192 return EFI_SUCCESS; \r
3193}\r
3194\r
3195/**\r
4d4deaac 3196 Submit data for a form.\r
b18e7050
ED
3197\r
3198 @param FormSet FormSet data structure.\r
3199 @param Form Form data structure.\r
7936fb6a 3200\r
3201 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 3202 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 3203\r
3204**/\r
3205EFI_STATUS\r
4d4deaac 3206SubmitForForm (\r
7936fb6a 3207 IN FORM_BROWSER_FORMSET *FormSet,\r
4d4deaac 3208 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3209 )\r
3210{\r
3211 EFI_STATUS Status;\r
3212 LIST_ENTRY *Link;\r
3213 EFI_STRING ConfigResp;\r
3214 EFI_STRING Progress;\r
94f3aae7 3215 BROWSER_STORAGE *Storage;\r
b18e7050 3216 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
fdd530d6
DB
3217 BOOLEAN SubmitFormFail;\r
3218\r
3219 SubmitFormFail = FALSE;\r
7936fb6a 3220\r
4d4deaac
ED
3221 if (!IsNvUpdateRequiredForForm (Form)) {\r
3222 return EFI_SUCCESS;\r
3223 }\r
3224\r
3225 Status = NoSubmitCheck (FormSet, &Form, NULL);\r
3226 if (EFI_ERROR (Status)) {\r
3227 return Status;\r
3228 }\r
3229\r
3230 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3231 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3232 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3233 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
3234\r
3235 Storage = ConfigInfo->Storage;\r
3236 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3237 continue;\r
3238 }\r
3239\r
3240 //\r
3241 // Skip if there is no RequestElement\r
3242 //\r
3243 if (ConfigInfo->ElementCount == 0) {\r
3244 continue;\r
3245 }\r
3246\r
3247 //\r
3248 // 1. Prepare <ConfigResp>\r
3249 //\r
3250 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
3251 if (EFI_ERROR (Status)) {\r
3252 return Status;\r
3253 }\r
3254\r
3255 //\r
3256 // 2. Set value to hii config routine protocol.\r
3257 //\r
3258 Status = mHiiConfigRouting->RouteConfig (\r
3259 mHiiConfigRouting,\r
3260 ConfigResp,\r
3261 &Progress\r
3262 );\r
4d4deaac
ED
3263\r
3264 if (EFI_ERROR (Status)) {\r
8066b27e
DB
3265 //\r
3266 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
3267 //\r
fdd530d6 3268 SubmitFormFail = TRUE;\r
8066b27e 3269 GetSyncRestoreConfigRequest (ConfigInfo->Storage, ConfigInfo->ConfigRequest, Progress, &ConfigInfo->RestoreConfigRequest, &ConfigInfo->SyncConfigRequest);\r
4d4deaac 3270 InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
fa209e8c 3271 FreePool (ConfigResp);\r
4d4deaac
ED
3272 continue;\r
3273 }\r
3274\r
fa209e8c 3275 FreePool (ConfigResp);\r
4d4deaac
ED
3276 //\r
3277 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
3278 //\r
3279 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
3280 }\r
3281\r
48a9d5f7 3282 //\r
4d4deaac 3283 // 4. Process the save failed storage.\r
48a9d5f7 3284 //\r
4d4deaac
ED
3285 if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3286 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3287 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3288 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3289 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3290 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
8066b27e
DB
3291 //\r
3292 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3293 // base on the SyncConfigRequest to Sync the buffer.\r
3294 //\r
3295 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->RestoreConfigRequest, FALSE);\r
3296 FreePool (ConfigInfo->RestoreConfigRequest);\r
3297 ConfigInfo->RestoreConfigRequest = NULL;\r
3298 if (ConfigInfo->SyncConfigRequest != NULL) {\r
3299 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->SyncConfigRequest, TRUE);\r
3300 FreePool (ConfigInfo->SyncConfigRequest);\r
3301 ConfigInfo->SyncConfigRequest = NULL;\r
3302 }\r
4d4deaac
ED
3303\r
3304 Status = EFI_SUCCESS;\r
3305 }\r
b6f07bdd 3306 SendDiscardInfoToDriver (FormSet,Form);\r
4d4deaac
ED
3307 } else {\r
3308 Status = EFI_UNSUPPORTED;\r
3309 }\r
3310\r
3311 //\r
3312 // Free Form save fail list.\r
3313 //\r
3314 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3315 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3316 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3317 RemoveEntryList (&ConfigInfo->SaveFailLink);\r
3318 }\r
48a9d5f7
LG
3319 }\r
3320\r
7936fb6a 3321 //\r
4d4deaac 3322 // 5. Update the NV flag.\r
7936fb6a 3323 //\r
4d4deaac
ED
3324 ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
3325\r
3cb44c20
DB
3326 //\r
3327 // 6 Call callback with Submitted type to inform the driver.\r
3328 //\r
fdd530d6
DB
3329 if (!SubmitFormFail) {\r
3330 SubmitCallback (FormSet, Form);\r
3331 }\r
3cb44c20 3332\r
4d4deaac
ED
3333 return Status;\r
3334}\r
3335\r
3336/**\r
3337 Submit data for a formset.\r
3338\r
3339 @param FormSet FormSet data structure.\r
3340 @param SkipProcessFail Whether skip to process the save failed storage.\r
3341 If submit formset is called when do system level save, \r
3342 set this value to true and process the failed formset \r
3343 together. \r
3344 if submit formset is called when do formset level save,\r
3345 set the value to false and process the failed storage\r
3346 right after process all storages for this formset.\r
3347\r
3348 @retval EFI_SUCCESS The function completed successfully.\r
3349 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3350\r
3351**/\r
3352EFI_STATUS\r
3353SubmitForFormSet (\r
3354 IN FORM_BROWSER_FORMSET *FormSet,\r
3355 IN BOOLEAN SkipProcessFail\r
3356 )\r
3357{\r
3358 EFI_STATUS Status;\r
3359 LIST_ENTRY *Link;\r
3360 EFI_STRING ConfigResp;\r
3361 EFI_STRING Progress;\r
3362 BROWSER_STORAGE *Storage;\r
3363 FORMSET_STORAGE *FormSetStorage;\r
3364 FORM_BROWSER_FORM *Form;\r
3365 BOOLEAN HasInserted;\r
3366 FORM_BROWSER_STATEMENT *Question;\r
fdd530d6 3367 BOOLEAN SubmitFormSetFail;\r
b6f07bdd 3368 BOOLEAN DiscardChange;\r
4d4deaac
ED
3369\r
3370 HasInserted = FALSE;\r
fdd530d6 3371 SubmitFormSetFail = FALSE;\r
b6f07bdd 3372 DiscardChange = FALSE;\r
4d4deaac
ED
3373\r
3374 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
3375 return EFI_SUCCESS;\r
b18e7050 3376 }\r
4d4deaac
ED
3377\r
3378 Form = NULL; \r
3379 Status = NoSubmitCheck (FormSet, &Form, &Question);\r
7936fb6a 3380 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
3381 if (SkipProcessFail) {\r
3382 //\r
3383 // Process NO_SUBMIT check first, so insert it at head.\r
3384 //\r
3385 FormSet->SaveFailForm = Form;\r
3386 FormSet->SaveFailStatement = Question;\r
3387 InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3388 }\r
3389\r
7936fb6a 3390 return Status;\r
3391 }\r
3392\r
4d4deaac
ED
3393 Form = NULL;\r
3394 Question = NULL;\r
3395 //\r
3396 // Submit Buffer storage or Name/Value storage\r
3397 //\r
3398 Link = GetFirstNode (&FormSet->StorageListHead);\r
3399 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3400 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3401 Storage = FormSetStorage->BrowserStorage;\r
3402 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
7936fb6a 3403\r
4d4deaac
ED
3404 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3405 continue;\r
3406 }\r
7936fb6a 3407\r
4d4deaac
ED
3408 //\r
3409 // Skip if there is no RequestElement\r
3410 //\r
3411 if (FormSetStorage->ElementCount == 0) {\r
3412 continue;\r
3413 }\r
7936fb6a 3414\r
4d4deaac
ED
3415 //\r
3416 // 1. Prepare <ConfigResp>\r
3417 //\r
3418 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
3419 if (EFI_ERROR (Status)) {\r
3420 return Status;\r
3421 }\r
b18e7050 3422\r
4d4deaac
ED
3423 //\r
3424 // 2. Send <ConfigResp> to Routine config Protocol.\r
3425 //\r
3426 Status = mHiiConfigRouting->RouteConfig (\r
3427 mHiiConfigRouting,\r
3428 ConfigResp,\r
3429 &Progress\r
3430 );\r
3431 if (EFI_ERROR (Status)) {\r
8066b27e
DB
3432 //\r
3433 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
3434 //\r
fdd530d6 3435 SubmitFormSetFail = TRUE;\r
8066b27e 3436 GetSyncRestoreConfigRequest (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, Progress, &FormSetStorage->RestoreConfigRequest, &FormSetStorage->SyncConfigRequest);\r
4d4deaac
ED
3437 InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
3438 if (!HasInserted) {\r
3439 //\r
3440 // Call submit formset for system level, save the formset info\r
3441 // and process later.\r
3442 //\r
3443 FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
3444 ASSERT (Form != NULL && Question != NULL);\r
3445 FormSet->SaveFailForm = Form;\r
3446 FormSet->SaveFailStatement = Question;\r
3447 if (SkipProcessFail) {\r
3448 InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3449 }\r
3450 HasInserted = TRUE;\r
b18e7050 3451 }\r
7248790e 3452\r
b18e7050 3453 FreePool (ConfigResp);\r
4d4deaac 3454 continue;\r
7936fb6a 3455 }\r
3456\r
4d4deaac 3457 FreePool (ConfigResp);\r
cce6230f 3458 //\r
4d4deaac 3459 // 3. Config success, update storage shadow Buffer\r
7936fb6a 3460 //\r
4d4deaac
ED
3461 SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
3462 }\r
b18e7050 3463\r
4d4deaac
ED
3464 //\r
3465 // 4. Has save fail storage need to handle.\r
3466 //\r
3467 if (Form != NULL) {\r
3468 if (!SkipProcessFail) {\r
b18e7050 3469 //\r
4d4deaac 3470 // If not in system level, just handl the save failed storage here.\r
b18e7050 3471 //\r
4d4deaac 3472 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
b6f07bdd 3473 DiscardChange = TRUE;\r
4d4deaac
ED
3474 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3475 while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
3476 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3477 Storage = FormSetStorage->BrowserStorage;\r
3478 Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
8066b27e
DB
3479 //\r
3480 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3481 // base on the SyncConfigRequest to Sync the buffer.\r
3482 //\r
3483 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
3484 FreePool (FormSetStorage->RestoreConfigRequest);\r
3485 FormSetStorage->RestoreConfigRequest = NULL;\r
3486 if (FormSetStorage->SyncConfigRequest != NULL) {\r
3487 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
3488 FreePool (FormSetStorage->SyncConfigRequest);\r
3489 FormSetStorage->SyncConfigRequest = NULL;\r
3490 }\r
4d4deaac
ED
3491\r
3492 Status = EFI_SUCCESS;\r
3493 }\r
3494 } else {\r
3495 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3496\r
3497 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3498 gCurrentSelection->Handle = FormSet->HiiHandle;\r
3499 CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
3500 gCurrentSelection->FormId = Form->FormId;\r
3501 gCurrentSelection->QuestionId = Question->QuestionId;\r
3502\r
3503 Status = EFI_UNSUPPORTED;\r
7936fb6a 3504 }\r
b18e7050 3505\r
7248790e 3506 //\r
4d4deaac 3507 // Free FormSet save fail list.\r
7248790e 3508 //\r
4d4deaac
ED
3509 while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
3510 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3511 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3512 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
b18e7050 3513 }\r
4d4deaac 3514 } else {\r
b18e7050 3515 //\r
4d4deaac 3516 // If in system level, just return error and handle the failed formset later.\r
b18e7050 3517 //\r
4d4deaac
ED
3518 Status = EFI_UNSUPPORTED;\r
3519 }\r
3520 }\r
3521\r
b6f07bdd
DB
3522 //\r
3523 // If user discard the change, send the discard info to driver.\r
3524 //\r
3525 if (DiscardChange) {\r
3526 Link = GetFirstNode (&FormSet->FormListHead);\r
3527 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3528 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3529 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3530 //\r
3531 // Call callback with Changed type to inform the driver.\r
3532 //\r
3533 SendDiscardInfoToDriver (FormSet, Form);\r
3534 }\r
3535 }\r
3536\r
4d4deaac
ED
3537 //\r
3538 // 5. Update the NV flag.\r
3539 // \r
3540 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
3541\r
3cb44c20
DB
3542 //\r
3543 // 6. Call callback with Submitted type to inform the driver.\r
3544 //\r
fdd530d6
DB
3545 if (!SubmitFormSetFail) {\r
3546 SubmitCallback (FormSet, NULL);\r
3547 }\r
3cb44c20 3548\r
4d4deaac
ED
3549 return Status;\r
3550}\r
3551\r
3552/**\r
3553 Submit data for all formsets.\r
3554\r
3555 @retval EFI_SUCCESS The function completed successfully.\r
3556 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3557\r
3558**/\r
3559EFI_STATUS\r
3560SubmitForSystem (\r
3561 VOID\r
3562 )\r
3563{\r
3564 EFI_STATUS Status;\r
3565 LIST_ENTRY *Link;\r
91927805 3566 LIST_ENTRY *FormLink;\r
4d4deaac 3567 LIST_ENTRY *StorageLink;\r
4d4deaac
ED
3568 FORMSET_STORAGE *FormSetStorage;\r
3569 FORM_BROWSER_FORM *Form;\r
3570 FORM_BROWSER_FORMSET *LocalFormSet;\r
3571 UINT32 UserSelection;\r
3572 FORM_BROWSER_STATEMENT *Question;\r
3573\r
3574 mSystemSubmit = TRUE;\r
3575 Link = GetFirstNode (&gBrowserFormSetList);\r
3576 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3577 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3578 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3579 if (!ValidateFormSet(LocalFormSet)) {\r
3580 continue;\r
3581 }\r
3582\r
3583 Status = SubmitForFormSet (LocalFormSet, TRUE);\r
3584 if (EFI_ERROR (Status)) {\r
3585 continue;\r
7936fb6a 3586 }\r
7936fb6a 3587\r
cce6230f 3588 //\r
4d4deaac
ED
3589 // Remove maintain backup list after save except for the current using FormSet.\r
3590 // \r
3591 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3592 CleanBrowserStorage(LocalFormSet);\r
3593 RemoveEntryList (&LocalFormSet->Link);\r
3594 DestroyFormSet (LocalFormSet);\r
3595 }\r
3596 }\r
3597 mSystemSubmit = FALSE;\r
3598\r
3599 Status = EFI_SUCCESS;\r
3600\r
3601 //\r
3602 // Process the save failed formsets.\r
3603 //\r
3604 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3605 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3606 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3607 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3608\r
3609 if (!ValidateFormSet(LocalFormSet)) {\r
3610 continue;\r
3611 }\r
3612\r
3613 Form = LocalFormSet->SaveFailForm;\r
3614 Question= LocalFormSet->SaveFailStatement;\r
48a9d5f7
LG
3615\r
3616 //\r
4d4deaac 3617 // Confirm with user, get user input.\r
48a9d5f7 3618 //\r
4d4deaac
ED
3619 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3620 //\r
3621 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
3622 //\r
3623 UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3624 } else {\r
3625 UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3626 }\r
3627\r
3628 if (UserSelection == BROWSER_ACTION_DISCARD) {\r
3629 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3630 StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
3631 while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
3632 FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
4d4deaac
ED
3633 StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
3634\r
3635 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3636 }\r
3637 } else {\r
3638 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3639 while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
3640 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
4d4deaac 3641 StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
8066b27e
DB
3642 //\r
3643 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
3644 // base on the SyncConfigRequest to Sync the buffer.\r
3645 //\r
3646 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
3647 FreePool (FormSetStorage->RestoreConfigRequest);\r
3648 FormSetStorage->RestoreConfigRequest = NULL;\r
3649 if ( FormSetStorage->SyncConfigRequest != NULL) {\r
3650 SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
3651 FreePool (FormSetStorage->SyncConfigRequest);\r
3652 FormSetStorage->SyncConfigRequest = NULL;\r
3653 }\r
4d4deaac 3654 }\r
938baa1f 3655 }\r
4d4deaac 3656\r
91927805
DB
3657 FormLink = GetFirstNode (&LocalFormSet->FormListHead);\r
3658 while (!IsNull (&LocalFormSet->FormListHead, FormLink)) {\r
3659 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
3660 FormLink = GetNextNode (&LocalFormSet->FormListHead, FormLink);\r
b6f07bdd
DB
3661 //\r
3662 // Call callback with Changed type to inform the driver.\r
3663 //\r
3664 SendDiscardInfoToDriver (LocalFormSet, Form);\r
3665 }\r
3666\r
48a9d5f7 3667 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
0a6f8af5 3668 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7 3669 RemoveEntryList (&LocalFormSet->Link);\r
4d4deaac 3670 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
48a9d5f7 3671 DestroyFormSet (LocalFormSet);\r
4d4deaac
ED
3672 } else {\r
3673 ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
48a9d5f7 3674 }\r
4d4deaac
ED
3675 } else {\r
3676 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3677 NoSubmitCheck (LocalFormSet, &Form, &Question);\r
3678 }\r
3679\r
3680 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3681\r
3682 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3683 gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
3684 CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
3685 gCurrentSelection->FormId = Form->FormId;\r
3686 gCurrentSelection->QuestionId = Question->QuestionId;\r
3687\r
3688 Status = EFI_UNSUPPORTED;\r
3689 break;\r
48a9d5f7 3690 }\r
7936fb6a 3691 }\r
3692\r
4d4deaac
ED
3693 //\r
3694 // Clean the list which will not process.\r
3695 //\r
3696 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3697 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3698 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3699 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3700\r
3701 while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3702 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3703 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3704 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3705 }\r
3706 }\r
3707\r
3708 return Status;\r
3709}\r
3710\r
3711/**\r
3712 Submit data based on the input Setting level (Form, FormSet or System).\r
3713\r
3714 @param FormSet FormSet data structure.\r
3715 @param Form Form data structure.\r
3716 @param SettingScope Setting Scope for Submit action.\r
3717\r
3718 @retval EFI_SUCCESS The function completed successfully.\r
3719 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3720\r
3721**/\r
3722EFI_STATUS\r
3723SubmitForm (\r
3724 IN FORM_BROWSER_FORMSET *FormSet,\r
3725 IN FORM_BROWSER_FORM *Form,\r
3726 IN BROWSER_SETTING_SCOPE SettingScope\r
3727 )\r
3728{\r
3729 EFI_STATUS Status;\r
3730\r
3731 switch (SettingScope) {\r
3732 case FormLevel:\r
3733 Status = SubmitForForm(FormSet, Form);\r
3734 break;\r
3735\r
3736 case FormSetLevel:\r
3737 Status = SubmitForFormSet (FormSet, FALSE);\r
3738 break;\r
3739\r
3740 case SystemLevel:\r
3741 Status = SubmitForSystem ();\r
3742 break;\r
3743\r
3744 default:\r
3745 Status = EFI_UNSUPPORTED;\r
3746 break;\r
3747 }\r
3748\r
3749 return Status;\r
7936fb6a 3750}\r
3751\r
ee31d1be 3752/**\r
7a9612ce
ED
3753 Converts the unicode character of the string from uppercase to lowercase.\r
3754 This is a internal function.\r
ee31d1be 3755\r
7a9612ce 3756 @param ConfigString String to be converted\r
ee31d1be
ED
3757\r
3758**/\r
7a9612ce
ED
3759VOID\r
3760EFIAPI\r
3761HiiToLower (\r
3762 IN EFI_STRING ConfigString\r
ee31d1be
ED
3763 )\r
3764{\r
7a9612ce
ED
3765 EFI_STRING String;\r
3766 BOOLEAN Lower;\r
ee31d1be 3767\r
7a9612ce 3768 ASSERT (ConfigString != NULL);\r
ee31d1be
ED
3769\r
3770 //\r
7a9612ce 3771 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
ee31d1be 3772 //\r
7a9612ce
ED
3773 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
3774 if (*String == L'=') {\r
3775 Lower = TRUE;\r
3776 } else if (*String == L'&') {\r
3777 Lower = FALSE;\r
3778 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
3779 *String = (CHAR16) (*String - L'A' + L'a');\r
3780 }\r
ee31d1be 3781 }\r
7a9612ce 3782}\r
ee31d1be 3783\r
7a9612ce
ED
3784/**\r
3785 Find the point in the ConfigResp string for this question.\r
3786\r
3787 @param Question The question.\r
3788 @param ConfigResp Get ConfigResp string.\r
3789\r
3790 @retval point to the offset where is for this question.\r
3791\r
3792**/\r
3793CHAR16 *\r
3794GetOffsetFromConfigResp (\r
3795 IN FORM_BROWSER_STATEMENT *Question,\r
3796 IN CHAR16 *ConfigResp\r
3797 )\r
3798{\r
3799 CHAR16 *RequestElement;\r
3800 CHAR16 *BlockData;\r
ee31d1be
ED
3801\r
3802 //\r
7a9612ce 3803 // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
ee31d1be 3804 //\r
7a9612ce
ED
3805 if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3806 RequestElement = StrStr (ConfigResp, Question->VariableName);\r
3807 if (RequestElement != NULL) {\r
3808 //\r
3809 // Skip the "VariableName=" field.\r
3810 //\r
3811 RequestElement += StrLen (Question->VariableName) + 1;\r
3812 }\r
ee31d1be 3813\r
7a9612ce 3814 return RequestElement;\r
ee31d1be
ED
3815 }\r
3816\r
3817 //\r
7a9612ce 3818 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
ee31d1be 3819 //\r
7a9612ce 3820\r
f3587039
DB
3821 //\r
3822 // Convert all hex digits in ConfigResp to lower case before searching.\r
3823 //\r
3824 HiiToLower (ConfigResp);\r
3825\r
ee31d1be 3826 //\r
7a9612ce 3827 // 1. Directly use Question->BlockName to find.\r
ee31d1be 3828 //\r
7a9612ce
ED
3829 RequestElement = StrStr (ConfigResp, Question->BlockName);\r
3830 if (RequestElement != NULL) {\r
3831 //\r
3832 // Skip the "Question->BlockName&VALUE=" field.\r
3833 //\r
3834 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
3835 return RequestElement;\r
7248790e 3836 }\r
7a9612ce 3837 \r
ee31d1be 3838 //\r
7a9612ce 3839 // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
ee31d1be 3840 //\r
7a9612ce
ED
3841 BlockData = AllocateCopyPool (StrSize(Question->BlockName), Question->BlockName);\r
3842 ASSERT (BlockData != NULL);\r
3843 HiiToLower (BlockData);\r
3844 RequestElement = StrStr (ConfigResp, BlockData);\r
3845 FreePool (BlockData);\r
3846\r
3847 if (RequestElement != NULL) {\r
ee31d1be 3848 //\r
7a9612ce 3849 // Skip the "Question->BlockName&VALUE=" field.\r
ee31d1be 3850 //\r
7a9612ce 3851 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
ee31d1be 3852 }\r
7a9612ce
ED
3853\r
3854 return RequestElement;\r
3855}\r
3856\r
3857/**\r
3858 Get Question default value from AltCfg string.\r
3859\r
3860 @param FormSet The form set.\r
3861 @param Form The form\r
3862 @param Question The question.\r
3863\r
3864 @retval EFI_SUCCESS Question is reset to default value.\r
3865\r
3866**/\r
3867EFI_STATUS\r
3868GetDefaultValueFromAltCfg (\r
3869 IN FORM_BROWSER_FORMSET *FormSet,\r
3870 IN FORM_BROWSER_FORM *Form,\r
3871 IN OUT FORM_BROWSER_STATEMENT *Question\r
3872 )\r
3873{ \r
3874 BROWSER_STORAGE *Storage;\r
3875 FORMSET_STORAGE *FormSetStorage;\r
3876 CHAR16 *ConfigResp;\r
3877 CHAR16 *Value;\r
3878 LIST_ENTRY *Link;\r
3879 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
3880\r
3881 Storage = Question->Storage;\r
3882 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3883 return EFI_NOT_FOUND;\r
ee31d1be 3884 }\r
ee31d1be
ED
3885\r
3886 //\r
7a9612ce
ED
3887 // Try to get AltCfg string from form. If not found it, then\r
3888 // try to get it from formset.\r
ee31d1be 3889 //\r
7a9612ce
ED
3890 ConfigResp = NULL;\r
3891 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3892 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3893 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3894 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
ee31d1be 3895\r
7a9612ce
ED
3896 if (Storage == ConfigInfo->Storage) {\r
3897 ConfigResp = ConfigInfo->ConfigAltResp;\r
3898 break;\r
ee31d1be 3899 }\r
7a9612ce
ED
3900 }\r
3901\r
3902 if (ConfigResp == NULL) {\r
3903 Link = GetFirstNode (&FormSet->StorageListHead);\r
3904 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3905 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3906 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3907\r
3908 if (Storage == FormSetStorage->BrowserStorage) {\r
3909 ConfigResp = FormSetStorage->ConfigAltResp;\r
3910 break;\r
25361615
ED
3911 }\r
3912 }\r
3913 }\r
b9feb4bd 3914\r
7a9612ce
ED
3915 if (ConfigResp == NULL) {\r
3916 return EFI_NOT_FOUND;\r
7c6c064c
ED
3917 }\r
3918\r
7a9612ce
ED
3919 Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
3920 if (Value == NULL) {\r
3921 return EFI_NOT_FOUND;\r
7c6c064c
ED
3922 }\r
3923\r
7a9612ce 3924 return BufferToValue (Question, Value);\r
7c6c064c
ED
3925}\r
3926\r
3927/**\r
3928 Get default Id value used for browser.\r
3929\r
3930 @param DefaultId The default id value used by hii.\r
3931\r
3932 @retval Browser used default value.\r
3933\r
3934**/\r
3935INTN\r
3936GetDefaultIdForCallBack (\r
3937 UINTN DefaultId\r
3938 )\r
3939{ \r
3940 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3941 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
3942 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3943 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
3944 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
3945 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
3946 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
3947 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
3948 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
3949 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
3950 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
3951 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
3952 } else {\r
3953 return -1;\r
3954 }\r
3955}\r
3956\r
3957\r
3958\r
3959/**\r
3960 Return data element in an Array by its Index.\r
3961\r
3962 @param Array The data array.\r
3963 @param Type Type of the data in this array.\r
3964 @param Index Zero based index for data in this array.\r
3965\r
3966 @retval Value The data to be returned\r
3967\r
3968**/\r
3969UINT64\r
3970GetArrayData (\r
3971 IN VOID *Array,\r
3972 IN UINT8 Type,\r
3973 IN UINTN Index\r
3974 )\r
3975{\r
3976 UINT64 Data;\r
3977\r
3978 ASSERT (Array != NULL);\r
3979\r
3980 Data = 0;\r
3981 switch (Type) {\r
3982 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3983 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
3984 break;\r
3985\r
3986 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3987 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
3988 break;\r
3989\r
3990 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3991 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
3992 break;\r
3993\r
3994 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3995 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
3996 break;\r
3997\r
3998 default:\r
3999 break;\r
4000 }\r
4001\r
4002 return Data;\r
4003}\r
4004\r
4005\r
4006/**\r
4007 Set value of a data element in an Array by its Index.\r
4008\r
4009 @param Array The data array.\r
4010 @param Type Type of the data in this array.\r
4011 @param Index Zero based index for data in this array.\r
4012 @param Value The value to be set.\r
4013\r
4014**/\r
4015VOID\r
4016SetArrayData (\r
4017 IN VOID *Array,\r
4018 IN UINT8 Type,\r
4019 IN UINTN Index,\r
4020 IN UINT64 Value\r
4021 )\r
4022{\r
4023\r
4024 ASSERT (Array != NULL);\r
b9feb4bd 4025\r
7c6c064c
ED
4026 switch (Type) {\r
4027 case EFI_IFR_TYPE_NUM_SIZE_8:\r
4028 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
4029 break;\r
25361615 4030\r
7c6c064c
ED
4031 case EFI_IFR_TYPE_NUM_SIZE_16:\r
4032 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
4033 break;\r
4034\r
4035 case EFI_IFR_TYPE_NUM_SIZE_32:\r
4036 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
4037 break;\r
4038\r
4039 case EFI_IFR_TYPE_NUM_SIZE_64:\r
4040 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
4041 break;\r
4042\r
4043 default:\r
4044 break;\r
4045 }\r
ee31d1be
ED
4046}\r
4047\r
4048/**\r
7c6c064c 4049 Search an Option of a Question by its value.\r
ee31d1be 4050\r
7c6c064c
ED
4051 @param Question The Question\r
4052 @param OptionValue Value for Option to be searched.\r
ee31d1be 4053\r
7c6c064c
ED
4054 @retval Pointer Pointer to the found Option.\r
4055 @retval NULL Option not found.\r
ee31d1be
ED
4056\r
4057**/\r
7c6c064c
ED
4058QUESTION_OPTION *\r
4059ValueToOption (\r
4060 IN FORM_BROWSER_STATEMENT *Question,\r
4061 IN EFI_HII_VALUE *OptionValue\r
ee31d1be 4062 )\r
7c6c064c
ED
4063{\r
4064 LIST_ENTRY *Link;\r
4065 QUESTION_OPTION *Option;\r
4066 INTN Result;\r
4067\r
4068 Link = GetFirstNode (&Question->OptionListHead);\r
4069 while (!IsNull (&Question->OptionListHead, Link)) {\r
4070 Option = QUESTION_OPTION_FROM_LINK (Link);\r
4071\r
4072 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
4073 //\r
4074 // Check the suppressif condition, only a valid option can be return.\r
4075 //\r
4076 if ((Option->SuppressExpression == NULL) ||\r
4077 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
4078 return Option;\r
4079 }\r
4080 }\r
4081\r
4082 Link = GetNextNode (&Question->OptionListHead, Link);\r
ee31d1be 4083 }\r
7c6c064c
ED
4084\r
4085 return NULL;\r
ee31d1be 4086}\r
7936fb6a 4087\r
7c6c064c 4088\r
7936fb6a 4089/**\r
4090 Reset Question to its default value.\r
4091\r
4092 @param FormSet The form set.\r
4093 @param Form The form.\r
4094 @param Question The question.\r
4095 @param DefaultId The Class of the default.\r
4096\r
4097 @retval EFI_SUCCESS Question is reset to default value.\r
4098\r
4099**/\r
4100EFI_STATUS\r
4101GetQuestionDefault (\r
4102 IN FORM_BROWSER_FORMSET *FormSet,\r
4103 IN FORM_BROWSER_FORM *Form,\r
4104 IN FORM_BROWSER_STATEMENT *Question,\r
4105 IN UINT16 DefaultId\r
4106 )\r
4107{\r
4108 EFI_STATUS Status;\r
4109 LIST_ENTRY *Link;\r
4110 QUESTION_DEFAULT *Default;\r
4111 QUESTION_OPTION *Option;\r
4112 EFI_HII_VALUE *HiiValue;\r
4113 UINT8 Index;\r
086cd2c8 4114 EFI_STRING StrValue;\r
ee31d1be
ED
4115 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4116 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
4117 INTN Action;\r
061d5462 4118 CHAR16 *NewString;\r
7f36d629 4119 EFI_IFR_TYPE_VALUE *TypeValue;\r
75596726
DB
4120 UINT16 OriginalDefaultId;\r
4121 FORMSET_DEFAULTSTORE *DefaultStore;\r
4122 LIST_ENTRY *DefaultLink;\r
7936fb6a 4123\r
48a9d5f7 4124 Status = EFI_NOT_FOUND;\r
086cd2c8 4125 StrValue = NULL;\r
75596726
DB
4126 OriginalDefaultId = DefaultId;\r
4127 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
7936fb6a 4128\r
4129 //\r
4130 // Statement don't have storage, skip them\r
4131 //\r
4132 if (Question->QuestionId == 0) {\r
4133 return Status;\r
4134 }\r
4135\r
4136 //\r
ee31d1be
ED
4137 // There are Five ways to specify default value for a Question:\r
4138 // 1, use call back function (highest priority)\r
4139 // 2, use ExtractConfig function\r
4140 // 3, use nested EFI_IFR_DEFAULT \r
4141 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
4142 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 4143 //\r
75596726 4144ReGetDefault:\r
7936fb6a 4145 HiiValue = &Question->HiiValue;\r
7f36d629 4146 TypeValue = &HiiValue->Value;\r
fa8ee0ad 4147 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
7f36d629
DB
4148 //\r
4149 // For orderedlist, need to pass the BufferValue to Callback function.\r
4150 //\r
4151 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
4152 }\r
7936fb6a 4153\r
ee31d1be
ED
4154 //\r
4155 // Get Question defaut value from call back function.\r
4156 //\r
4157 ConfigAccess = FormSet->ConfigAccess;\r
4158 Action = GetDefaultIdForCallBack (DefaultId);\r
4159 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
4160 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
4161 Status = ConfigAccess->Callback (\r
4162 ConfigAccess,\r
4163 Action,\r
4164 Question->QuestionId,\r
4165 HiiValue->Type,\r
7f36d629 4166 TypeValue,\r
ee31d1be
ED
4167 &ActionRequest\r
4168 );\r
4169 if (!EFI_ERROR (Status)) {\r
061d5462
ED
4170 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
4171 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
4172 ASSERT (NewString != NULL);\r
4173\r
4174 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
4175 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
05b2f9c9 4176 ZeroMem (Question->BufferValue, Question->StorageWidth);\r
061d5462
ED
4177 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
4178 } else {\r
4179 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
4180 }\r
4181\r
4182 FreePool (NewString);\r
4183 }\r
ee31d1be
ED
4184 return Status;\r
4185 }\r
4186 }\r
4187\r
4188 //\r
4189 // Get default value from altcfg string.\r
4190 //\r
4191 if (ConfigAccess != NULL) { \r
7a9612ce 4192 Status = GetDefaultValueFromAltCfg(FormSet, Form, Question);\r
ee31d1be
ED
4193 if (!EFI_ERROR (Status)) {\r
4194 return Status;\r
4195 }\r
4196 }\r
4197\r
7936fb6a 4198 //\r
4199 // EFI_IFR_DEFAULT has highest priority\r
4200 //\r
4201 if (!IsListEmpty (&Question->DefaultListHead)) {\r
4202 Link = GetFirstNode (&Question->DefaultListHead);\r
4203 while (!IsNull (&Question->DefaultListHead, Link)) {\r
4204 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
4205\r
4206 if (Default->DefaultId == DefaultId) {\r
4207 if (Default->ValueExpression != NULL) {\r
4208 //\r
4209 // Default is provided by an Expression, evaluate it\r
4210 //\r
4211 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
4212 if (EFI_ERROR (Status)) {\r
4213 return Status;\r
4214 }\r
4215\r
901ba0e7
ED
4216 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
4217 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
4218 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
4219 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
4220 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
4221 } else {\r
4222 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
4223 Question->HiiValue.BufferLen = Question->StorageWidth;\r
4224 }\r
4225 FreePool (Default->ValueExpression->Result.Buffer);\r
4226 }\r
4227 HiiValue->Type = Default->ValueExpression->Result.Type;\r
4228 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 4229 } else {\r
4230 //\r
4231 // Default value is embedded in EFI_IFR_DEFAULT\r
4232 //\r
0b567d18
ED
4233 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
4234 ASSERT (HiiValue->Buffer != NULL);\r
4235 CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
4236 } else {\r
4237 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
4238 }\r
7936fb6a 4239 }\r
4240\r
086cd2c8
LG
4241 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
4242 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
4243 if (StrValue == NULL) {\r
4244 return EFI_NOT_FOUND;\r
4245 }\r
ba944801 4246 if (Question->StorageWidth > StrSize (StrValue)) {\r
05b2f9c9 4247 ZeroMem (Question->BufferValue, Question->StorageWidth);\r
ba944801
ED
4248 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
4249 } else {\r
4250 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
4251 }\r
086cd2c8
LG
4252 }\r
4253\r
7936fb6a 4254 return EFI_SUCCESS;\r
4255 }\r
4256\r
4257 Link = GetNextNode (&Question->DefaultListHead, Link);\r
4258 }\r
4259 }\r
4260\r
4261 //\r
4262 // EFI_ONE_OF_OPTION\r
4263 //\r
4264 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
4265 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
4266 //\r
4267 // OneOfOption could only provide Standard and Manufacturing default\r
4268 //\r
4269 Link = GetFirstNode (&Question->OptionListHead);\r
4270 while (!IsNull (&Question->OptionListHead, Link)) {\r
4271 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4272 Link = GetNextNode (&Question->OptionListHead, Link);\r
4273\r
4274 if ((Option->SuppressExpression != NULL) &&\r
4275 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4276 continue;\r
4277 }\r
7936fb6a 4278\r
4279 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
4280 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
4281 ) {\r
4282 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
4283\r
4284 return EFI_SUCCESS;\r
4285 }\r
7936fb6a 4286 }\r
4287 }\r
4288 }\r
4289\r
4290 //\r
4291 // EFI_IFR_CHECKBOX - lowest priority\r
4292 //\r
4293 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
4294 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
4295 //\r
4296 // Checkbox could only provide Standard and Manufacturing default\r
4297 //\r
4298 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
4299 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
4300 ) {\r
4301 HiiValue->Value.b = TRUE;\r
7936fb6a 4302 }\r
4303\r
4304 return EFI_SUCCESS;\r
4305 }\r
4306 }\r
4307\r
4308 //\r
75596726
DB
4309 // 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
4310 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
4311 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
4312 //\r
4313 while (!IsNull(&FormSet->DefaultStoreListHead, DefaultLink)) {\r
4314 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);\r
4315 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,DefaultLink);\r
4316 DefaultId = DefaultStore->DefaultId;\r
4317 if (DefaultId == OriginalDefaultId) {\r
4318 continue;\r
4319 }\r
4320 goto ReGetDefault;\r
4321 }\r
4322\r
4323 //\r
4324 // For Questions without default value for all the default id in the DefaultStoreList.\r
7936fb6a 4325 //\r
48a9d5f7 4326 Status = EFI_NOT_FOUND;\r
7936fb6a 4327 switch (Question->Operand) {\r
93e59f76
LG
4328 case EFI_IFR_CHECKBOX_OP:\r
4329 HiiValue->Value.b = FALSE;\r
4330 Status = EFI_SUCCESS;\r
4331 break;\r
4332\r
cf4c5a42
LG
4333 case EFI_IFR_NUMERIC_OP:\r
4334 //\r
4335 // Take minimum value as numeric default value\r
4336 //\r
afc9bf79
ED
4337 if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {\r
4338 //\r
4339 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
4340 //\r
4341 switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {\r
4342 case EFI_IFR_NUMERIC_SIZE_1:\r
4343 if (((INT8) HiiValue->Value.u8 < (INT8) Question->Minimum) || ((INT8) HiiValue->Value.u8 > (INT8) Question->Maximum)) {\r
4344 HiiValue->Value.u8 = (UINT8) Question->Minimum;\r
4345 Status = EFI_SUCCESS;\r
4346 }\r
4347 break;\r
4348 case EFI_IFR_NUMERIC_SIZE_2:\r
4349 if (((INT16) HiiValue->Value.u16 < (INT16) Question->Minimum) || ((INT16) HiiValue->Value.u16 > (INT16) Question->Maximum)) {\r
4350 HiiValue->Value.u16 = (UINT16) Question->Minimum;\r
4351 Status = EFI_SUCCESS;\r
4352 }\r
4353 break;\r
4354 case EFI_IFR_NUMERIC_SIZE_4:\r
4355 if (((INT32) HiiValue->Value.u32 < (INT32) Question->Minimum) || ((INT32) HiiValue->Value.u32 > (INT32) Question->Maximum)) {\r
4356 HiiValue->Value.u32 = (UINT32) Question->Minimum;\r
4357 Status = EFI_SUCCESS;\r
4358 }\r
4359 break;\r
4360 case EFI_IFR_NUMERIC_SIZE_8:\r
4361 if (((INT64) HiiValue->Value.u64 < (INT64) Question->Minimum) || ((INT64) HiiValue->Value.u64 > (INT64) Question->Maximum)) {\r
4362 HiiValue->Value.u64 = Question->Minimum;\r
4363 Status = EFI_SUCCESS;\r
4364 }\r
4365 break;\r
4366 default:\r
4367 break; \r
4368 }\r
4369 } else {\r
4370 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
4371 HiiValue->Value.u64 = Question->Minimum;\r
4372 Status = EFI_SUCCESS;\r
4373 }\r
cf4c5a42
LG
4374 }\r
4375 break;\r
4376\r
7936fb6a 4377 case EFI_IFR_ONE_OF_OP:\r
4378 //\r
4379 // Take first oneof option as oneof's default value\r
4380 //\r
d66e6c16 4381 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed 4382 Link = GetFirstNode (&Question->OptionListHead);\r
82612023 4383 while (!IsNull (&Question->OptionListHead, Link)) {\r
0a1147ed 4384 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4385 Link = GetNextNode (&Question->OptionListHead, Link);\r
4386\r
4387 if ((Option->SuppressExpression != NULL) &&\r
4388 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4389 continue;\r
4390 }\r
4391\r
0a1147ed 4392 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 4393 Status = EFI_SUCCESS;\r
82612023 4394 break;\r
0a1147ed 4395 }\r
7936fb6a 4396 }\r
4397 break;\r
4398\r
4399 case EFI_IFR_ORDERED_LIST_OP:\r
4400 //\r
4401 // Take option sequence in IFR as ordered list's default value\r
4402 //\r
4403 Index = 0;\r
4404 Link = GetFirstNode (&Question->OptionListHead);\r
4405 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 4406 Status = EFI_SUCCESS;\r
7936fb6a 4407 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4408 Link = GetNextNode (&Question->OptionListHead, Link);\r
4409\r
4410 if ((Option->SuppressExpression != NULL) &&\r
4411 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4412 continue;\r
4413 }\r
7936fb6a 4414\r
d02847d3 4415 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 4416\r
4417 Index++;\r
4418 if (Index >= Question->MaxContainers) {\r
4419 break;\r
4420 }\r
7936fb6a 4421 }\r
4422 break;\r
4423\r
4424 default:\r
7936fb6a 4425 break;\r
4426 }\r
4427\r
4428 return Status;\r
4429}\r
4430\r
7a9612ce
ED
4431/**\r
4432 Get AltCfg string for current form.\r
4433\r
4434 @param FormSet Form data structure.\r
4435 @param Form Form data structure.\r
4436 @param DefaultId The Class of the default.\r
787fc2a6 4437 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4438\r
4439**/\r
4440VOID\r
4441ExtractAltCfgForForm (\r
4442 IN FORM_BROWSER_FORMSET *FormSet,\r
4443 IN FORM_BROWSER_FORM *Form,\r
787fc2a6
ED
4444 IN UINT16 DefaultId,\r
4445 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4446 )\r
4447{\r
4448 EFI_STATUS Status;\r
4449 LIST_ENTRY *Link;\r
4450 CHAR16 *ConfigResp;\r
4451 CHAR16 *Progress;\r
4452 CHAR16 *Result;\r
4453 BROWSER_STORAGE *Storage;\r
4454 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4455 FORMSET_STORAGE *FormSetStorage;\r
4456\r
4457 //\r
4458 // Check whether has get AltCfg string for this formset.\r
4459 // If yes, no need to get AltCfg for form.\r
4460 //\r
4461 Link = GetFirstNode (&FormSet->StorageListHead);\r
4462 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4463 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4464 Storage = FormSetStorage->BrowserStorage;\r
4465 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
787fc2a6
ED
4466 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4467 continue;\r
4468 }\r
7a9612ce
ED
4469\r
4470 if (Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE &&\r
4471 FormSetStorage->ElementCount != 0 &&\r
787fc2a6 4472 FormSetStorage->HasCallAltCfg) {\r
7a9612ce
ED
4473 return;\r
4474 }\r
4475 }\r
4476\r
4477 //\r
4478 // Get AltCfg string for each form.\r
4479 //\r
4480 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4481 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4482 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4483 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4484\r
4485 Storage = ConfigInfo->Storage;\r
787fc2a6
ED
4486 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4487 continue;\r
4488 }\r
4489\r
7a9612ce
ED
4490 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4491 continue;\r
4492 }\r
4493\r
4494 //\r
4495 // 1. Skip if there is no RequestElement\r
4496 //\r
4497 if (ConfigInfo->ElementCount == 0) {\r
4498 continue;\r
4499 }\r
4500\r
4501 //\r
4502 // 2. Get value through hii config routine protocol.\r
4503 //\r
4504 Status = mHiiConfigRouting->ExtractConfig (\r
4505 mHiiConfigRouting,\r
4506 ConfigInfo->ConfigRequest,\r
4507 &Progress,\r
4508 &Result\r
4509 );\r
4510 if (EFI_ERROR (Status)) {\r
4511 continue;\r
4512 }\r
4513\r
4514 //\r
4515 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4516 // Get the default configuration string according to the default ID.\r
4517 //\r
4518 Status = mHiiConfigRouting->GetAltConfig (\r
4519 mHiiConfigRouting,\r
4520 Result,\r
4521 &Storage->Guid,\r
4522 Storage->Name,\r
4523 NULL,\r
4524 &DefaultId, // it can be NULL to get the current setting.\r
4525 &ConfigResp\r
4526 );\r
4527 FreePool (Result);\r
4528 if (EFI_ERROR (Status)) {\r
4529 continue;\r
4530 }\r
4531\r
4532 ConfigInfo->ConfigAltResp = ConfigResp;\r
4533 }\r
4534}\r
4535\r
4536/**\r
4537 Clean AltCfg string for current form.\r
4538\r
4539 @param Form Form data structure.\r
4540\r
4541**/\r
4542VOID\r
4543CleanAltCfgForForm (\r
4544 IN FORM_BROWSER_FORM *Form\r
4545 )\r
4546{\r
4547 LIST_ENTRY *Link;\r
4548 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4549\r
4550 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4551 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4552 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4553 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4554\r
4555 if (ConfigInfo->ConfigAltResp != NULL) {\r
4556 FreePool (ConfigInfo->ConfigAltResp);\r
4557 ConfigInfo->ConfigAltResp = NULL;\r
4558 }\r
4559 }\r
4560}\r
4561\r
4562/**\r
4563 Get AltCfg string for current formset.\r
4564\r
4565 @param FormSet Form data structure.\r
4566 @param DefaultId The Class of the default.\r
787fc2a6 4567 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4568\r
4569**/\r
4570VOID\r
4571ExtractAltCfgForFormSet (\r
4572 IN FORM_BROWSER_FORMSET *FormSet,\r
787fc2a6
ED
4573 IN UINT16 DefaultId,\r
4574 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4575 )\r
4576{\r
4577 EFI_STATUS Status;\r
4578 LIST_ENTRY *Link;\r
4579 CHAR16 *ConfigResp;\r
4580 CHAR16 *Progress;\r
4581 CHAR16 *Result;\r
4582 BROWSER_STORAGE *Storage;\r
4583 FORMSET_STORAGE *FormSetStorage;\r
4584\r
4585 Link = GetFirstNode (&FormSet->StorageListHead);\r
4586 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4587 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4588 Storage = FormSetStorage->BrowserStorage;\r
4589 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4590\r
787fc2a6
ED
4591 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4592 continue;\r
4593 }\r
4594\r
7a9612ce
ED
4595 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4596 continue;\r
4597 }\r
4598\r
4599 //\r
4600 // 1. Skip if there is no RequestElement\r
4601 //\r
4602 if (FormSetStorage->ElementCount == 0) {\r
4603 continue;\r
4604 }\r
4605\r
787fc2a6
ED
4606 FormSetStorage->HasCallAltCfg = TRUE;\r
4607\r
7a9612ce
ED
4608 //\r
4609 // 2. Get value through hii config routine protocol.\r
4610 //\r
4611 Status = mHiiConfigRouting->ExtractConfig (\r
4612 mHiiConfigRouting,\r
4613 FormSetStorage->ConfigRequest,\r
4614 &Progress,\r
4615 &Result\r
4616 );\r
4617 if (EFI_ERROR (Status)) {\r
4618 continue;\r
4619 }\r
4620\r
4621 //\r
4622 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4623 // Get the default configuration string according to the default ID.\r
4624 //\r
4625 Status = mHiiConfigRouting->GetAltConfig (\r
4626 mHiiConfigRouting,\r
4627 Result,\r
4628 &Storage->Guid,\r
4629 Storage->Name,\r
4630 NULL,\r
4631 &DefaultId, // it can be NULL to get the current setting.\r
4632 &ConfigResp\r
4633 );\r
4634\r
4635 FreePool (Result);\r
4636 if (EFI_ERROR (Status)) {\r
4637 continue;\r
4638 }\r
4639\r
4640 FormSetStorage->ConfigAltResp = ConfigResp;\r
4641 }\r
4642\r
4643}\r
4644\r
4645/**\r
4646 Clean AltCfg string for current formset.\r
4647\r
4648 @param FormSet Form data structure.\r
4649\r
4650**/\r
4651VOID\r
4652CleanAltCfgForFormSet (\r
4653 IN FORM_BROWSER_FORMSET *FormSet\r
4654 )\r
4655{\r
4656 LIST_ENTRY *Link;\r
4657 FORMSET_STORAGE *FormSetStorage;\r
4658\r
4659 Link = GetFirstNode (&FormSet->StorageListHead);\r
4660 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4661 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4662 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4663\r
4664 if (FormSetStorage->ConfigAltResp != NULL) {\r
4665 FreePool (FormSetStorage->ConfigAltResp);\r
4666 FormSetStorage->ConfigAltResp = NULL;\r
4667 }\r
787fc2a6
ED
4668\r
4669 FormSetStorage->HasCallAltCfg = FALSE;\r
7a9612ce
ED
4670 }\r
4671}\r
7936fb6a 4672\r
4673/**\r
9776099f 4674 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 4675\r
09cdd7d2
ED
4676 GetDefaultValueScope parameter decides which questions will reset \r
4677 to its default value.\r
4678\r
7936fb6a 4679 @param FormSet FormSet data structure.\r
48a9d5f7 4680 @param Form Form data structure.\r
7936fb6a 4681 @param DefaultId The Class of the default.\r
48a9d5f7 4682 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 4683 @param GetDefaultValueScope Get default value scope.\r
3347d410 4684 @param Storage Get default value only for this storage.\r
9776099f
ED
4685 @param RetrieveValueFirst Whether call the retrieve call back to\r
4686 get the initial value before get default\r
4687 value.\r
787fc2a6 4688 @param SkipGetAltCfg Whether skip the get altcfg string process.\r
7936fb6a 4689\r
4690 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 4691 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 4692\r
4693**/\r
4694EFI_STATUS\r
48a9d5f7 4695ExtractDefault (\r
7936fb6a 4696 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
4697 IN FORM_BROWSER_FORM *Form,\r
4698 IN UINT16 DefaultId,\r
3347d410 4699 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 4700 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
94f3aae7 4701 IN BROWSER_STORAGE *Storage OPTIONAL,\r
787fc2a6
ED
4702 IN BOOLEAN RetrieveValueFirst,\r
4703 IN BOOLEAN SkipGetAltCfg\r
7936fb6a 4704 )\r
4705{\r
4706 EFI_STATUS Status;\r
4f33c838 4707 LIST_ENTRY *FormLink;\r
48a9d5f7 4708 LIST_ENTRY *Link;\r
7936fb6a 4709 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7 4710 FORM_BROWSER_FORMSET *LocalFormSet;\r
6e74560f 4711 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 4712\r
9776099f
ED
4713 Status = EFI_SUCCESS;\r
4714\r
48a9d5f7
LG
4715 //\r
4716 // Check the supported setting level.\r
4717 //\r
09cdd7d2
ED
4718 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
4719 return EFI_UNSUPPORTED;\r
4720 }\r
4721\r
4722 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
4723 return EFI_UNSUPPORTED;\r
4724 }\r
7a9612ce 4725\r
48a9d5f7 4726 if (SettingScope == FormLevel) {\r
7a9612ce
ED
4727 //\r
4728 // Prepare the AltCfg String for form.\r
4729 //\r
787fc2a6
ED
4730 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4731 ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
4732 }\r
7a9612ce 4733\r
8d00a0f1 4734 //\r
4f33c838 4735 // Extract Form default\r
8d00a0f1 4736 //\r
48a9d5f7
LG
4737 Link = GetFirstNode (&Form->StatementListHead);\r
4738 while (!IsNull (&Form->StatementListHead, Link)) {\r
4739 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4740 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
4741\r
4742 //\r
4743 // If get default value only for this storage, check the storage first.\r
4744 //\r
09cdd7d2
ED
4745 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
4746 continue;\r
4747 }\r
4748\r
4749 //\r
4750 // If get default value only for no storage question, just skip the question which has storage.\r
4751 //\r
4752 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
4753 continue;\r
4754 }\r
4755\r
4f33c838
ED
4756 //\r
4757 // If Question is disabled, don't reset it to default\r
4758 //\r
31585af4
ED
4759 if (Question->Expression != NULL) {\r
4760 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
4761 continue;\r
4762 }\r
8d00a0f1 4763 }\r
9776099f
ED
4764\r
4765 if (RetrieveValueFirst) {\r
4766 //\r
4767 // Call the Retrieve call back to get the initial question value.\r
4768 //\r
061d5462 4769 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
9776099f
ED
4770 }\r
4771\r
4f33c838 4772 //\r
9776099f 4773 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 4774 //\r
9776099f
ED
4775 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
4776 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
4777 if (EFI_ERROR (Status)) {\r
4778 continue;\r
4779 }\r
4f33c838 4780 }\r
9776099f 4781\r
4f33c838
ED
4782 //\r
4783 // Synchronize Buffer storage's Edit buffer\r
4784 //\r
4785 if ((Question->Storage != NULL) &&\r
4786 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 4787 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
4788 }\r
4789 }\r
7a9612ce
ED
4790\r
4791 //\r
4792 // Clean the AltCfg String.\r
4793 //\r
787fc2a6
ED
4794 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4795 CleanAltCfgForForm(Form);\r
4796 }\r
48a9d5f7 4797 } else if (SettingScope == FormSetLevel) {\r
7a9612ce
ED
4798 //\r
4799 // Prepare the AltCfg String for formset.\r
4800 //\r
787fc2a6
ED
4801 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4802 ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
4803 }\r
7a9612ce 4804\r
48a9d5f7
LG
4805 FormLink = GetFirstNode (&FormSet->FormListHead);\r
4806 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
4807 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
787fc2a6 4808 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
48a9d5f7
LG
4809 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
4810 }\r
7a9612ce
ED
4811\r
4812 //\r
4813 // Clean the AltCfg String.\r
4814 //\r
787fc2a6
ED
4815 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4816 CleanAltCfgForFormSet (FormSet);\r
4817 }\r
48a9d5f7
LG
4818 } else if (SettingScope == SystemLevel) {\r
4819 //\r
7c6c064c 4820 // Preload all Hii formset.\r
48a9d5f7 4821 //\r
7c6c064c 4822 LoadAllHiiFormset();\r
6e74560f
ED
4823\r
4824 OldFormSet = mSystemLevelFormSet;\r
4825\r
48a9d5f7
LG
4826 //\r
4827 // Set Default Value for each FormSet in the maintain list.\r
4828 //\r
4829 Link = GetFirstNode (&gBrowserFormSetList);\r
4830 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4831 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 4832 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
4833 if (!ValidateFormSet(LocalFormSet)) {\r
4834 continue;\r
4835 }\r
6e74560f
ED
4836\r
4837 mSystemLevelFormSet = LocalFormSet;\r
4838\r
787fc2a6 4839 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
7936fb6a 4840 }\r
6e74560f
ED
4841\r
4842 mSystemLevelFormSet = OldFormSet;\r
7936fb6a 4843 }\r
4844\r
4845 return EFI_SUCCESS;\r
4846}\r
4847\r
7c6c064c
ED
4848\r
4849/**\r
4850 Validate whether this question's value has changed.\r
4851\r
4852 @param FormSet FormSet data structure.\r
4853 @param Form Form data structure.\r
4854 @param Question Question to be initialized.\r
4855 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
4856\r
4857 @retval TRUE Question's value has changed.\r
4858 @retval FALSE Question's value has not changed\r
4859\r
4860**/\r
4861BOOLEAN\r
4862IsQuestionValueChanged (\r
4863 IN FORM_BROWSER_FORMSET *FormSet,\r
4864 IN FORM_BROWSER_FORM *Form,\r
4865 IN OUT FORM_BROWSER_STATEMENT *Question,\r
4866 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
4867 )\r
4868{\r
4869 EFI_HII_VALUE BackUpValue;\r
4870 CHAR8 *BackUpBuffer;\r
4d4deaac
ED
4871 EFI_HII_VALUE BackUpValue2;\r
4872 CHAR8 *BackUpBuffer2;\r
7c6c064c
ED
4873 EFI_STATUS Status;\r
4874 BOOLEAN ValueChanged;\r
4875 UINTN BufferWidth;\r
4876\r
4877 //\r
4878 // For quetion without storage, always mark it as data not changed.\r
4879 //\r
4880 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
4881 return FALSE;\r
4882 }\r
4883\r
4884 BackUpBuffer = NULL;\r
4d4deaac 4885 BackUpBuffer2 = NULL;\r
7c6c064c
ED
4886 ValueChanged = FALSE;\r
4887\r
4888 switch (Question->Operand) {\r
4889 case EFI_IFR_ORDERED_LIST_OP:\r
4890 BufferWidth = Question->StorageWidth;\r
4891 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4892 ASSERT (BackUpBuffer != NULL);\r
4893 break;\r
4894\r
4895 case EFI_IFR_STRING_OP:\r
4896 case EFI_IFR_PASSWORD_OP:\r
4897 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4898 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4899 ASSERT (BackUpBuffer != NULL);\r
4900 break;\r
4901\r
4902 default:\r
4903 BufferWidth = 0;\r
4904 break;\r
4905 }\r
4906 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4907\r
4d4deaac
ED
4908 if (GetValueFrom == GetSetValueWithBothBuffer) {\r
4909 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4910 ASSERT_EFI_ERROR(Status);\r
7c6c064c 4911\r
4d4deaac
ED
4912 switch (Question->Operand) {\r
4913 case EFI_IFR_ORDERED_LIST_OP:\r
4914 BufferWidth = Question->StorageWidth;\r
4915 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4916 ASSERT (BackUpBuffer2 != NULL);\r
4917 break;\r
4918\r
4919 case EFI_IFR_STRING_OP:\r
4920 case EFI_IFR_PASSWORD_OP:\r
4921 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4922 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4923 ASSERT (BackUpBuffer2 != NULL);\r
4924 break;\r
4925\r
4926 default:\r
4927 BufferWidth = 0;\r
4928 break;\r
4929 }\r
4930 CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4931\r
4932 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
4933 ASSERT_EFI_ERROR(Status);\r
4934\r
4935 if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4936 CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
4937 ValueChanged = TRUE;\r
4938 }\r
4939 } else {\r
4940 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
4941 ASSERT_EFI_ERROR(Status);\r
4942\r
4943 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4944 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
4945 ValueChanged = TRUE;\r
4946 }\r
7c6c064c
ED
4947 }\r
4948\r
4949 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
7c6c064c 4950 if (BackUpBuffer != NULL) {\r
e77d2f9d 4951 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
7c6c064c
ED
4952 FreePool (BackUpBuffer);\r
4953 }\r
4954\r
4d4deaac
ED
4955 if (BackUpBuffer2 != NULL) {\r
4956 FreePool (BackUpBuffer2);\r
4957 }\r
4958\r
892eccc8
ED
4959 Question->ValueChanged = ValueChanged;\r
4960\r
7c6c064c
ED
4961 return ValueChanged;\r
4962}\r
4963\r
7936fb6a 4964/**\r
4965 Initialize Question's Edit copy from Storage.\r
4966\r
eccfeab1
LG
4967 @param Selection Selection contains the information about \r
4968 the Selection, form and formset to be displayed.\r
4969 Selection action may be updated in retrieve callback.\r
7d1b202d 4970 If Selection is NULL, only initialize Question value.\r
7936fb6a 4971 @param FormSet FormSet data structure.\r
4972 @param Form Form data structure.\r
4973\r
4974 @retval EFI_SUCCESS The function completed successfully.\r
4975\r
4976**/\r
4977EFI_STATUS\r
4978LoadFormConfig (\r
eccfeab1
LG
4979 IN OUT UI_MENU_SELECTION *Selection,\r
4980 IN FORM_BROWSER_FORMSET *FormSet,\r
4981 IN FORM_BROWSER_FORM *Form\r
7936fb6a 4982 )\r
4983{\r
eccfeab1
LG
4984 EFI_STATUS Status;\r
4985 LIST_ENTRY *Link;\r
4986 FORM_BROWSER_STATEMENT *Question;\r
eccfeab1 4987 \r
7936fb6a 4988 Link = GetFirstNode (&Form->StatementListHead);\r
4989 while (!IsNull (&Form->StatementListHead, Link)) {\r
4990 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4991\r
4992 //\r
4993 // Initialize local copy of Value for each Question\r
4994 //\r
7c6c064c
ED
4995 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
4996 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
4997 } else {\r
4998 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4999 }\r
7936fb6a 5000 if (EFI_ERROR (Status)) {\r
5001 return Status;\r
5002 }\r
e2100bfa
ED
5003\r
5004 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
5005 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
5006 }\r
5007\r
7936fb6a 5008 Link = GetNextNode (&Form->StatementListHead, Link);\r
5009 }\r
5010\r
5011 return EFI_SUCCESS;\r
5012}\r
5013\r
d66e6c16 5014/**\r
5015 Initialize Question's Edit copy from Storage for the whole Formset.\r
5016\r
eccfeab1
LG
5017 @param Selection Selection contains the information about \r
5018 the Selection, form and formset to be displayed.\r
5019 Selection action may be updated in retrieve callback.\r
7d1b202d 5020 If Selection is NULL, only initialize Question value.\r
d66e6c16 5021 @param FormSet FormSet data structure.\r
5022\r
5023 @retval EFI_SUCCESS The function completed successfully.\r
5024\r
5025**/\r
5026EFI_STATUS\r
5027LoadFormSetConfig (\r
eccfeab1
LG
5028 IN OUT UI_MENU_SELECTION *Selection,\r
5029 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 5030 )\r
5031{\r
eccfeab1
LG
5032 EFI_STATUS Status;\r
5033 LIST_ENTRY *Link;\r
5034 FORM_BROWSER_FORM *Form;\r
d66e6c16 5035\r
5036 Link = GetFirstNode (&FormSet->FormListHead);\r
5037 while (!IsNull (&FormSet->FormListHead, Link)) {\r
5038 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5039\r
5040 //\r
5041 // Initialize local copy of Value for each Form\r
5042 //\r
eccfeab1 5043 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 5044 if (EFI_ERROR (Status)) {\r
5045 return Status;\r
5046 }\r
5047\r
5048 Link = GetNextNode (&FormSet->FormListHead, Link);\r
5049 }\r
5050\r
7c6c064c
ED
5051 //\r
5052 // Finished question initialization.\r
5053 // \r
5054 FormSet->QuestionInited = TRUE;\r
5055\r
d66e6c16 5056 return EFI_SUCCESS;\r
5057}\r
5058\r
0a6f8af5
ED
5059/**\r
5060 Remove the Request element from the Config Request.\r
5061\r
5062 @param Storage Pointer to the browser storage.\r
5063 @param RequestElement The pointer to the Request element.\r
5064\r
5065**/\r
5066VOID\r
5067RemoveElement (\r
5068 IN OUT BROWSER_STORAGE *Storage,\r
5069 IN CHAR16 *RequestElement\r
5070 )\r
5071{\r
5072 CHAR16 *NewStr;\r
5073 CHAR16 *DestStr;\r
5074\r
5075 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
5076\r
5077 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
5078\r
5079 if (NewStr == NULL) {\r
5080 return;\r
5081 }\r
5082\r
5083 //\r
5084 // Remove this element from this ConfigRequest.\r
5085 //\r
5086 DestStr = NewStr;\r
5087 NewStr += StrLen (RequestElement);\r
5088 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
5089 \r
5090 Storage->SpareStrLen += StrLen (RequestElement); \r
5091}\r
5092\r
5093/**\r
5094 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
5095\r
a35ecb75 5096 @param Storage Pointer to the formset storage.\r
0a6f8af5
ED
5097 @param ConfigRequest The pointer to the Request element.\r
5098\r
5099**/\r
5100VOID\r
5101RemoveConfigRequest (\r
a35ecb75 5102 FORMSET_STORAGE *Storage,\r
0a6f8af5
ED
5103 CHAR16 *ConfigRequest\r
5104 )\r
5105{\r
5106 CHAR16 *RequestElement;\r
5107 CHAR16 *NextRequestElement;\r
5108 CHAR16 *SearchKey;\r
5109\r
7c6c064c
ED
5110 //\r
5111 // No request element in it, just return.\r
5112 //\r
5113 if (ConfigRequest == NULL) {\r
5114 return;\r
5115 }\r
5116\r
a35ecb75 5117 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
5118 //\r
5119 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
5120 //\r
5121 SearchKey = L"&";\r
5122 } else {\r
5123 //\r
5124 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
5125 //\r
5126 SearchKey = L"&OFFSET";\r
5127 }\r
5128\r
5129 //\r
5130 // Find SearchKey storage\r
5131 //\r
a35ecb75 5132 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
5133 RequestElement = StrStr (ConfigRequest, L"PATH");\r
5134 ASSERT (RequestElement != NULL);\r
5135 RequestElement = StrStr (RequestElement, SearchKey); \r
5136 } else {\r
5137 RequestElement = StrStr (ConfigRequest, SearchKey);\r
5138 }\r
5139\r
5140 while (RequestElement != NULL) {\r
5141 //\r
5142 // +1 to avoid find header itself.\r
5143 //\r
5144 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
5145\r
5146 //\r
5147 // The last Request element in configRequest string.\r
5148 //\r
5149 if (NextRequestElement != NULL) {\r
5150 //\r
5151 // Replace "&" with '\0'.\r
5152 //\r
5153 *NextRequestElement = L'\0';\r
5154 }\r
5155\r
a35ecb75 5156 RemoveElement (Storage->BrowserStorage, RequestElement);\r
0a6f8af5
ED
5157\r
5158 if (NextRequestElement != NULL) {\r
5159 //\r
5160 // Restore '&' with '\0' for later used.\r
5161 //\r
5162 *NextRequestElement = L'&';\r
5163 }\r
5164\r
5165 RequestElement = NextRequestElement;\r
5166 }\r
5167\r
5168 //\r
5169 // If no request element remain, just remove the ConfigRequest string.\r
5170 //\r
a35ecb75
ED
5171 if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
5172 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5173 Storage->BrowserStorage->ConfigRequest = NULL;\r
5174 Storage->BrowserStorage->SpareStrLen = 0;\r
0a6f8af5
ED
5175 }\r
5176}\r
5177\r
5178/**\r
5179 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
5180\r
5181 @param FormSet Pointer of the FormSet\r
5182\r
5183**/\r
5184VOID\r
5185CleanBrowserStorage (\r
5186 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5187 )\r
5188{\r
5189 LIST_ENTRY *Link;\r
5190 FORMSET_STORAGE *Storage;\r
5191\r
5192 Link = GetFirstNode (&FormSet->StorageListHead);\r
5193 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5194 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5195 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5196\r
fae73624
ED
5197 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
5198 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
5199 continue;\r
5200 }\r
0a6f8af5 5201\r
a35ecb75 5202 RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
fae73624
ED
5203 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
5204 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
5205 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
5206 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5dc6ab16 5207 Storage->BrowserStorage->ConfigRequest = NULL;\r
fae73624
ED
5208 }\r
5209 Storage->BrowserStorage->Initialized = FALSE;\r
0a6f8af5 5210 }\r
0a6f8af5
ED
5211 }\r
5212}\r
5213\r
efffd9c1
ED
5214/**\r
5215 Check whether current element in the ConfigReqeust string.\r
5216\r
5217 @param BrowserStorage Storage which includes ConfigReqeust.\r
5218 @param RequestElement New element need to check.\r
5219\r
5220 @retval TRUE The Element is in the ConfigReqeust string.\r
5221 @retval FALSE The Element not in the configReqeust String.\r
5222\r
5223**/\r
5224BOOLEAN \r
5225ElementValidation (\r
5226 BROWSER_STORAGE *BrowserStorage,\r
5227 CHAR16 *RequestElement\r
5228 )\r
5229{\r
5230 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
5231}\r
5232\r
5233/**\r
5234 Append the Request element to the Config Request.\r
5235\r
5236 @param ConfigRequest Current ConfigRequest info.\r
5237 @param SpareStrLen Current remain free buffer for config reqeust.\r
5238 @param RequestElement New Request element.\r
5239\r
5240**/\r
5241VOID\r
5242AppendConfigRequest (\r
5243 IN OUT CHAR16 **ConfigRequest,\r
5244 IN OUT UINTN *SpareStrLen,\r
5245 IN CHAR16 *RequestElement\r
5246 )\r
5247{\r
5248 CHAR16 *NewStr;\r
5249 UINTN StringSize;\r
5250 UINTN StrLength;\r
5ad66ec6 5251 UINTN MaxLen;\r
efffd9c1 5252\r
0a6f8af5 5253 StrLength = StrLen (RequestElement);\r
5ad66ec6
DB
5254 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
5255 MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
efffd9c1
ED
5256\r
5257 //\r
5258 // Append <RequestElement> to <ConfigRequest>\r
5259 //\r
5260 if (StrLength > *SpareStrLen) {\r
5261 //\r
5262 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
5263 //\r
5ad66ec6
DB
5264 MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
5265 NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
efffd9c1
ED
5266 ASSERT (NewStr != NULL);\r
5267\r
5268 if (*ConfigRequest != NULL) {\r
5269 CopyMem (NewStr, *ConfigRequest, StringSize);\r
5270 FreePool (*ConfigRequest);\r
5271 }\r
5272 *ConfigRequest = NewStr;\r
5273 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
5274 }\r
5275\r
5ad66ec6 5276 StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
efffd9c1
ED
5277 *SpareStrLen -= StrLength;\r
5278}\r
5279\r
5280/**\r
5281 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
5282\r
5283 @param Storage Form set Storage.\r
9d34cac8
ED
5284 @param Request The input request string.\r
5285 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
efffd9c1
ED
5286\r
5287 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
5288 @retval FALSE All elements covered by current used elements.\r
5289\r
5290**/\r
5291BOOLEAN \r
5292ConfigRequestAdjust (\r
9d34cac8
ED
5293 IN BROWSER_STORAGE *Storage,\r
5294 IN CHAR16 *Request,\r
5295 IN BOOLEAN RespString\r
efffd9c1
ED
5296 )\r
5297{\r
5298 CHAR16 *RequestElement;\r
5299 CHAR16 *NextRequestElement;\r
9d34cac8 5300 CHAR16 *NextElementBakup;\r
efffd9c1 5301 CHAR16 *SearchKey;\r
9d34cac8 5302 CHAR16 *ValueKey;\r
efffd9c1 5303 BOOLEAN RetVal;\r
9d34cac8 5304 CHAR16 *ConfigRequest;\r
efffd9c1 5305\r
efffd9c1 5306 RetVal = FALSE;\r
9d34cac8
ED
5307 NextElementBakup = NULL;\r
5308 ValueKey = NULL;\r
efffd9c1 5309\r
9d34cac8
ED
5310 if (Request != NULL) {\r
5311 ConfigRequest = Request;\r
5312 } else {\r
5313 ConfigRequest = Storage->ConfigRequest;\r
5314 }\r
5315\r
5316 if (Storage->ConfigRequest == NULL) {\r
5317 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
efffd9c1
ED
5318 return TRUE;\r
5319 }\r
5320\r
9d34cac8 5321 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
efffd9c1
ED
5322 //\r
5323 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
5324 //\r
5325 SearchKey = L"&";\r
5326 } else {\r
5327 //\r
5328 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
5329 //\r
5330 SearchKey = L"&OFFSET";\r
9d34cac8 5331 ValueKey = L"&VALUE";\r
efffd9c1
ED
5332 }\r
5333\r
efffd9c1
ED
5334 //\r
5335 // Find SearchKey storage\r
5336 //\r
9d34cac8
ED
5337 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
5338 RequestElement = StrStr (ConfigRequest, L"PATH");\r
efffd9c1
ED
5339 ASSERT (RequestElement != NULL);\r
5340 RequestElement = StrStr (RequestElement, SearchKey); \r
5341 } else {\r
9d34cac8 5342 RequestElement = StrStr (ConfigRequest, SearchKey);\r
efffd9c1
ED
5343 }\r
5344\r
5345 while (RequestElement != NULL) {\r
9d34cac8 5346\r
efffd9c1
ED
5347 //\r
5348 // +1 to avoid find header itself.\r
5349 //\r
5350 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
5351\r
5352 //\r
5353 // The last Request element in configRequest string.\r
5354 //\r
5355 if (NextRequestElement != NULL) {\r
9d34cac8
ED
5356 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5357 NextElementBakup = NextRequestElement;\r
5358 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 5359 ASSERT (NextRequestElement != NULL);\r
9d34cac8 5360 }\r
efffd9c1
ED
5361 //\r
5362 // Replace "&" with '\0'.\r
5363 //\r
5364 *NextRequestElement = L'\0';\r
9d34cac8
ED
5365 } else {\r
5366 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5367 NextElementBakup = NextRequestElement;\r
5368 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 5369 ASSERT (NextRequestElement != NULL);\r
9d34cac8
ED
5370 //\r
5371 // Replace "&" with '\0'.\r
5372 //\r
5373 *NextRequestElement = L'\0';\r
5374 }\r
efffd9c1
ED
5375 }\r
5376 \r
9d34cac8 5377 if (!ElementValidation (Storage, RequestElement)) {\r
efffd9c1
ED
5378 //\r
5379 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
5380 //\r
9d34cac8 5381 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
efffd9c1
ED
5382 RetVal = TRUE;\r
5383 }\r
5384\r
5385 if (NextRequestElement != NULL) {\r
5386 //\r
5387 // Restore '&' with '\0' for later used.\r
5388 //\r
5389 *NextRequestElement = L'&';\r
5390 }\r
5391\r
9d34cac8
ED
5392 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5393 RequestElement = NextElementBakup;\r
5394 } else {\r
5395 RequestElement = NextRequestElement;\r
7c6c064c 5396 }\r
efffd9c1
ED
5397 }\r
5398\r
5399 return RetVal;\r
5400}\r
5401\r
7936fb6a 5402/**\r
5403 Fill storage's edit copy with settings requested from Configuration Driver.\r
5404\r
5405 @param FormSet FormSet data structure.\r
5406 @param Storage Buffer Storage.\r
5407\r
7936fb6a 5408**/\r
7c6c064c 5409VOID\r
7936fb6a 5410LoadStorage (\r
5411 IN FORM_BROWSER_FORMSET *FormSet,\r
5412 IN FORMSET_STORAGE *Storage\r
5413 )\r
5414{\r
5415 EFI_STATUS Status;\r
5416 EFI_STRING Progress;\r
5417 EFI_STRING Result;\r
5418 CHAR16 *StrPtr;\r
98c4caa1
ED
5419 EFI_STRING ConfigRequest;\r
5420 UINTN StrLen;\r
5421\r
5422 ConfigRequest = NULL;\r
7936fb6a 5423\r
7c6c064c
ED
5424 switch (Storage->BrowserStorage->Type) {\r
5425 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
5426 return;\r
5427\r
5428 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
6e74560f 5429 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
9d34cac8 5430 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
7c6c064c
ED
5431 return;\r
5432 }\r
7c6c064c 5433 break;\r
cce6230f 5434\r
7c6c064c
ED
5435 case EFI_HII_VARSTORE_BUFFER:\r
5436 case EFI_HII_VARSTORE_NAME_VALUE:\r
5437 //\r
27c304f4 5438 // Skip if there is no RequestElement.\r
7c6c064c 5439 //\r
27c304f4 5440 if (Storage->ElementCount == 0) {\r
7c6c064c
ED
5441 return;\r
5442 }\r
27c304f4
ED
5443\r
5444 //\r
5445 // Just update the ConfigRequest, if storage already initialized. \r
5446 //\r
5447 if (Storage->BrowserStorage->Initialized) {\r
9d34cac8 5448 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
27c304f4
ED
5449 return;\r
5450 }\r
5451\r
fae73624 5452 Storage->BrowserStorage->Initialized = TRUE;\r
7c6c064c 5453 break;\r
7936fb6a 5454\r
7c6c064c 5455 default:\r
7248790e 5456 return;\r
7936fb6a 5457 }\r
7248790e 5458\r
27c304f4
ED
5459 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
5460 //\r
5461 // Create the config request string to get all fields for this storage.\r
5462 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
5463 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
5464 //\r
a35ecb75 5465 StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
27c304f4
ED
5466 ConfigRequest = AllocateZeroPool (StrLen);\r
5467 ASSERT (ConfigRequest != NULL);\r
5468 UnicodeSPrint (\r
5469 ConfigRequest, \r
5470 StrLen, \r
5471 L"%s&OFFSET=0&WIDTH=%04x", \r
a35ecb75 5472 Storage->ConfigHdr,\r
27c304f4
ED
5473 Storage->BrowserStorage->Size);\r
5474 } else {\r
5475 ConfigRequest = Storage->ConfigRequest;\r
5476 }\r
5477\r
7248790e
ED
5478 //\r
5479 // Request current settings from Configuration Driver\r
5480 //\r
5481 Status = mHiiConfigRouting->ExtractConfig (\r
5482 mHiiConfigRouting,\r
98c4caa1 5483 ConfigRequest,\r
7248790e
ED
5484 &Progress,\r
5485 &Result\r
5486 );\r
5487\r
5488 //\r
5489 // If get value fail, extract default from IFR binary\r
5490 //\r
5491 if (EFI_ERROR (Status)) {\r
787fc2a6 5492 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
7248790e
ED
5493 } else {\r
5494 //\r
5495 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
5496 //\r
5497 StrPtr = StrStr (Result, L"&GUID=");\r
5498 if (StrPtr != NULL) {\r
5499 *StrPtr = L'\0';\r
5500 }\r
5501 \r
5502 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
5503 FreePool (Result);\r
5504 }\r
5505\r
5506 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
5507\r
5508 //\r
5509 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
5510 //\r
4d4deaac 5511 SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
98c4caa1 5512\r
27c304f4 5513 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
98c4caa1
ED
5514 if (ConfigRequest != NULL) {\r
5515 FreePool (ConfigRequest);\r
5516 }\r
5517 }\r
7936fb6a 5518}\r
5519\r
892eccc8
ED
5520/**\r
5521 Get Value changed status from old question.\r
5522\r
5523 @param NewFormSet FormSet data structure.\r
5524 @param OldQuestion Old question which has value changed.\r
5525\r
5526**/\r
5527VOID\r
5528SyncStatusForQuestion (\r
5529 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5530 IN FORM_BROWSER_STATEMENT *OldQuestion\r
5531 )\r
5532{\r
5533 LIST_ENTRY *Link;\r
5534 LIST_ENTRY *QuestionLink;\r
5535 FORM_BROWSER_FORM *Form;\r
5536 FORM_BROWSER_STATEMENT *Question;\r
5537\r
5538 //\r
5539 // For each form in one formset.\r
5540 //\r
5541 Link = GetFirstNode (&NewFormSet->FormListHead);\r
5542 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
5543 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5544 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
5545\r
5546 //\r
5547 // for each question in one form.\r
5548 //\r
5549 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5550 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5551 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5552 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5553\r
5554 if (Question->QuestionId == OldQuestion->QuestionId) {\r
5555 Question->ValueChanged = TRUE;\r
5556 return;\r
5557 }\r
5558 }\r
5559 }\r
5560}\r
5561\r
5562/**\r
5563 Get Value changed status from old formset.\r
5564\r
5565 @param NewFormSet FormSet data structure.\r
5566 @param OldFormSet FormSet data structure.\r
5567\r
5568**/\r
5569VOID\r
5570SyncStatusForFormSet (\r
5571 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5572 IN FORM_BROWSER_FORMSET *OldFormSet\r
5573 )\r
5574{\r
5575 LIST_ENTRY *Link;\r
5576 LIST_ENTRY *QuestionLink;\r
5577 FORM_BROWSER_FORM *Form;\r
5578 FORM_BROWSER_STATEMENT *Question;\r
5579\r
5580 //\r
5581 // For each form in one formset.\r
5582 //\r
5583 Link = GetFirstNode (&OldFormSet->FormListHead);\r
5584 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
5585 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5586 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
5587\r
5588 //\r
5589 // for each question in one form.\r
5590 //\r
5591 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5592 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5593 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5594 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5595\r
5596 if (!Question->ValueChanged) {\r
5597 continue;\r
5598 }\r
5599\r
5600 //\r
5601 // Find the same question in new formset and update the value changed flag.\r
5602 //\r
5603 SyncStatusForQuestion (NewFormSet, Question);\r
5604 }\r
5605 }\r
5606}\r
5607\r
7936fb6a 5608/**\r
5609 Get current setting of Questions.\r
5610\r
5611 @param FormSet FormSet data structure.\r
5612\r
7936fb6a 5613**/\r
7c6c064c 5614VOID\r
7936fb6a 5615InitializeCurrentSetting (\r
5616 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5617 )\r
5618{\r
5619 LIST_ENTRY *Link;\r
5620 FORMSET_STORAGE *Storage;\r
7c6c064c 5621 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 5622\r
6e74560f
ED
5623 //\r
5624 // Try to find pre FormSet in the maintain backup list.\r
5625 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
5626 //\r
5627 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
5628 if (OldFormSet != NULL) {\r
892eccc8 5629 SyncStatusForFormSet (FormSet, OldFormSet);\r
6e74560f
ED
5630 RemoveEntryList (&OldFormSet->Link);\r
5631 DestroyFormSet (OldFormSet);\r
5632 }\r
5633 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
5634\r
1deb5cab
ED
5635 //\r
5636 // Extract default from IFR binary for no storage questions.\r
5637 // \r
787fc2a6 5638 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\r
1deb5cab 5639\r
7936fb6a 5640 //\r
5641 // Request current settings from Configuration Driver\r
5642 //\r
5643 Link = GetFirstNode (&FormSet->StorageListHead);\r
5644 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5645 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5646\r
7c6c064c 5647 LoadStorage (FormSet, Storage);\r
7936fb6a 5648\r
7936fb6a 5649 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5650 }\r
7936fb6a 5651}\r
5652\r
5653\r
5654/**\r
5655 Fetch the Ifr binary data of a FormSet.\r
5656\r
5657 @param Handle PackageList Handle\r
f5006bd9 5658 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5659 specified (NULL or zero GUID), take the first\r
5660 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5661 found in package list.\r
5662 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5663 @param BinaryLength The length of the FormSet IFR binary.\r
5664 @param BinaryData The buffer designed to receive the FormSet.\r
5665\r
5666 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
5667 BufferLength was updated.\r
5668 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
5669 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
5670 be found with the requested FormId.\r
5671\r
5672**/\r
5673EFI_STATUS\r
5674GetIfrBinaryData (\r
5675 IN EFI_HII_HANDLE Handle,\r
5676 IN OUT EFI_GUID *FormSetGuid,\r
5677 OUT UINTN *BinaryLength,\r
5678 OUT UINT8 **BinaryData\r
5679 )\r
5680{\r
5681 EFI_STATUS Status;\r
5682 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
5683 UINTN BufferSize;\r
5684 UINT8 *Package;\r
5685 UINT8 *OpCodeData;\r
5686 UINT32 Offset;\r
5687 UINT32 Offset2;\r
7936fb6a 5688 UINT32 PackageListLength;\r
5689 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
5690 UINT8 Index;\r
5691 UINT8 NumberOfClassGuid;\r
f5006bd9 5692 BOOLEAN ClassGuidMatch;\r
0a1147ed 5693 EFI_GUID *ClassGuid;\r
f5006bd9 5694 EFI_GUID *ComparingGuid;\r
7936fb6a 5695\r
5696 OpCodeData = NULL;\r
5697 Package = NULL;\r
0c66bc76 5698 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 5699\r
5700 //\r
f5006bd9 5701 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 5702 //\r
48a9d5f7
LG
5703 if (FormSetGuid == NULL) {\r
5704 ComparingGuid = &gZeroGuid;\r
7936fb6a 5705 } else {\r
f5006bd9 5706 ComparingGuid = FormSetGuid;\r
7936fb6a 5707 }\r
5708\r
5709 //\r
5710 // Get HII PackageList\r
5711 //\r
5712 BufferSize = 0;\r
5713 HiiPackageList = NULL;\r
5714 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5715 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5716 HiiPackageList = AllocatePool (BufferSize);\r
5717 ASSERT (HiiPackageList != NULL);\r
5718\r
5719 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5720 }\r
5721 if (EFI_ERROR (Status)) {\r
5722 return Status;\r
5723 }\r
db0bd81c 5724 ASSERT (HiiPackageList != NULL);\r
d66e6c16 5725\r
7936fb6a 5726 //\r
5727 // Get Form package from this HII package List\r
5728 //\r
5729 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
5730 Offset2 = 0;\r
5731 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
5732\r
f5006bd9 5733 ClassGuidMatch = FALSE;\r
7936fb6a 5734 while (Offset < PackageListLength) {\r
5735 Package = ((UINT8 *) HiiPackageList) + Offset;\r
5736 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
5737\r
8d00a0f1 5738 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 5739 //\r
5740 // Search FormSet in this Form Package\r
5741 //\r
5742 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
5743 while (Offset2 < PackageHeader.Length) {\r
5744 OpCodeData = Package + Offset2;\r
5745\r
5746 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
5747 //\r
f5006bd9 5748 // Try to compare against formset GUID\r
7936fb6a 5749 //\r
39cde03c 5750 if (IsZeroGuid (FormSetGuid) ||\r
48a9d5f7 5751 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 5752 break;\r
7936fb6a 5753 }\r
5754\r
d228526f
LG
5755 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
5756 //\r
5757 // Try to compare against formset class GUID\r
5758 //\r
5759 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
5760 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
5761 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
5762 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
5763 ClassGuidMatch = TRUE;\r
5764 break;\r
5765 }\r
5766 }\r
5767 if (ClassGuidMatch) {\r
f5006bd9 5768 break;\r
5769 }\r
d228526f
LG
5770 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
5771 ClassGuidMatch = TRUE;\r
7936fb6a 5772 break;\r
5773 }\r
5774 }\r
5775\r
5776 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
5777 }\r
5778\r
5779 if (Offset2 < PackageHeader.Length) {\r
5780 //\r
5781 // Target formset found\r
5782 //\r
5783 break;\r
5784 }\r
5785 }\r
5786\r
5787 Offset += PackageHeader.Length;\r
5788 }\r
5789\r
5790 if (Offset >= PackageListLength) {\r
5791 //\r
5792 // Form package not found in this Package List\r
5793 //\r
f4113e1f 5794 FreePool (HiiPackageList);\r
7936fb6a 5795 return EFI_NOT_FOUND;\r
5796 }\r
5797\r
48a9d5f7 5798 if (FormSetGuid != NULL) {\r
7936fb6a 5799 //\r
f5006bd9 5800 // Return the FormSet GUID\r
7936fb6a 5801 //\r
5802 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
5803 }\r
5804\r
5805 //\r
5806 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
5807 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
5808 // of the Form Package.\r
5809 //\r
5810 *BinaryLength = PackageHeader.Length - Offset2;\r
5811 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
5812\r
f4113e1f 5813 FreePool (HiiPackageList);\r
7936fb6a 5814\r
5815 if (*BinaryData == NULL) {\r
5816 return EFI_OUT_OF_RESOURCES;\r
5817 }\r
5818\r
5819 return EFI_SUCCESS;\r
5820}\r
5821\r
5822\r
5823/**\r
5824 Initialize the internal data structure of a FormSet.\r
5825\r
5826 @param Handle PackageList Handle\r
f5006bd9 5827 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5828 specified (NULL or zero GUID), take the first\r
5829 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5830 found in package list.\r
5831 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5832 @param FormSet FormSet data structure.\r
5833\r
5834 @retval EFI_SUCCESS The function completed successfully.\r
5835 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
5836\r
5837**/\r
5838EFI_STATUS\r
5839InitializeFormSet (\r
5840 IN EFI_HII_HANDLE Handle,\r
5841 IN OUT EFI_GUID *FormSetGuid,\r
7c6c064c 5842 OUT FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 5843 )\r
5844{\r
5845 EFI_STATUS Status;\r
5846 EFI_HANDLE DriverHandle;\r
7936fb6a 5847\r
5848 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
5849 if (EFI_ERROR (Status)) {\r
5850 return Status;\r
5851 }\r
5852\r
48a9d5f7 5853 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 5854 FormSet->HiiHandle = Handle;\r
5855 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
7c6c064c 5856 FormSet->QuestionInited = FALSE;\r
7936fb6a 5857\r
5858 //\r
5859 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
5860 //\r
5861 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
5862 if (EFI_ERROR (Status)) {\r
5863 return Status;\r
5864 }\r
5865 FormSet->DriverHandle = DriverHandle;\r
5866 Status = gBS->HandleProtocol (\r
5867 DriverHandle,\r
5868 &gEfiHiiConfigAccessProtocolGuid,\r
5869 (VOID **) &FormSet->ConfigAccess\r
5870 );\r
5871 if (EFI_ERROR (Status)) {\r
5872 //\r
5873 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
5874 // list, then there will be no configuration action required\r
5875 //\r
5876 FormSet->ConfigAccess = NULL;\r
5877 }\r
5878\r
5879 //\r
5880 // Parse the IFR binary OpCodes\r
5881 //\r
5882 Status = ParseOpCodes (FormSet);\r
25361615 5883\r
7c6c064c 5884 return Status;\r
7936fb6a 5885}\r
ce6d12cc 5886\r
5887\r
5888/**\r
5889 Save globals used by previous call to SendForm(). SendForm() may be called from \r
5890 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
5891 So, save globals of previous call to SendForm() and restore them upon exit.\r
5892\r
5893**/\r
5894VOID\r
5895SaveBrowserContext (\r
5896 VOID\r
5897 )\r
5898{\r
b6f61255
ED
5899 BROWSER_CONTEXT *Context;\r
5900 FORM_ENTRY_INFO *MenuList;\r
5901 FORM_BROWSER_FORMSET *FormSet;\r
ce6d12cc 5902\r
5903 gBrowserContextCount++;\r
5904 if (gBrowserContextCount == 1) {\r
5905 //\r
5906 // This is not reentry of SendForm(), no context to save\r
5907 //\r
5908 return;\r
5909 }\r
5910\r
5911 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
5912 ASSERT (Context != NULL);\r
5913\r
5914 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
5915\r
5916 //\r
5917 // Save FormBrowser context\r
5918 //\r
5a9f73bf 5919 Context->Selection = gCurrentSelection;\r
ce6d12cc 5920 Context->ResetRequired = gResetRequired;\r
f2e7732e
ED
5921 Context->FlagReconnect = gFlagReconnect;\r
5922 Context->CallbackReconnect = gCallbackReconnect;\r
7c6c064c
ED
5923 Context->ExitRequired = gExitRequired;\r
5924 Context->HiiHandle = mCurrentHiiHandle;\r
5a9f73bf
ED
5925 Context->FormId = mCurrentFormId;\r
5926 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
f4c3c923
ED
5927 Context->SystemLevelFormSet = mSystemLevelFormSet;\r
5928 Context->CurFakeQestId = mCurFakeQestId;\r
5929 Context->HiiPackageListUpdated = mHiiPackageListUpdated;\r
5930 Context->FinishRetrieveCall = mFinishRetrieveCall;\r
7c6c064c
ED
5931\r
5932 //\r
5933 // Save the menu history data.\r
5934 //\r
5935 InitializeListHead(&Context->FormHistoryList);\r
5936 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
5937 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
5938 RemoveEntryList (&MenuList->Link);\r
5939\r
5940 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
5941 }\r
ce6d12cc 5942\r
b6f61255
ED
5943 //\r
5944 // Save formset list.\r
5945 //\r
5946 InitializeListHead(&Context->FormSetList);\r
5947 while (!IsListEmpty (&gBrowserFormSetList)) {\r
5948 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList.ForwardLink);\r
5949 RemoveEntryList (&FormSet->Link);\r
5950\r
5951 InsertTailList(&Context->FormSetList, &FormSet->Link);\r
5952 }\r
5953\r
ce6d12cc 5954 //\r
5955 // Insert to FormBrowser context list\r
5956 //\r
5957 InsertHeadList (&gBrowserContextList, &Context->Link);\r
5958}\r
5959\r
5960\r
5961/**\r
5962 Restore globals used by previous call to SendForm().\r
5963\r
5964**/\r
5965VOID\r
5966RestoreBrowserContext (\r
5967 VOID\r
5968 )\r
5969{\r
5970 LIST_ENTRY *Link;\r
5971 BROWSER_CONTEXT *Context;\r
b6f61255
ED
5972 FORM_ENTRY_INFO *MenuList;\r
5973 FORM_BROWSER_FORMSET *FormSet;\r
ce6d12cc 5974\r
5975 ASSERT (gBrowserContextCount != 0);\r
5976 gBrowserContextCount--;\r
5977 if (gBrowserContextCount == 0) {\r
5978 //\r
5979 // This is not reentry of SendForm(), no context to restore\r
5980 //\r
5981 return;\r
5982 }\r
5983\r
5984 ASSERT (!IsListEmpty (&gBrowserContextList));\r
5985\r
5986 Link = GetFirstNode (&gBrowserContextList);\r
5987 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5988\r
5989 //\r
5990 // Restore FormBrowser context\r
5991 //\r
5a9f73bf 5992 gCurrentSelection = Context->Selection;\r
ce6d12cc 5993 gResetRequired = Context->ResetRequired;\r
f2e7732e
ED
5994 gFlagReconnect = Context->FlagReconnect;\r
5995 gCallbackReconnect = Context->CallbackReconnect;\r
7c6c064c
ED
5996 gExitRequired = Context->ExitRequired;\r
5997 mCurrentHiiHandle = Context->HiiHandle;\r
5a9f73bf
ED
5998 mCurrentFormId = Context->FormId;\r
5999 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
f4c3c923
ED
6000 mSystemLevelFormSet = Context->SystemLevelFormSet;\r
6001 mCurFakeQestId = Context->CurFakeQestId;\r
6002 mHiiPackageListUpdated = Context->HiiPackageListUpdated;\r
6003 mFinishRetrieveCall = Context->FinishRetrieveCall;\r
7c6c064c
ED
6004\r
6005 //\r
6006 // Restore the menu history data.\r
6007 //\r
6008 while (!IsListEmpty (&Context->FormHistoryList)) {\r
6009 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
6010 RemoveEntryList (&MenuList->Link);\r
6011\r
6012 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
6013 }\r
ce6d12cc 6014\r
b6f61255
ED
6015 //\r
6016 // Restore the Formset data.\r
6017 //\r
6018 while (!IsListEmpty (&Context->FormSetList)) {\r
6019 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Context->FormSetList.ForwardLink);\r
6020 RemoveEntryList (&FormSet->Link);\r
6021\r
6022 InsertTailList(&gBrowserFormSetList, &FormSet->Link);\r
6023 }\r
6024\r
ce6d12cc 6025 //\r
6026 // Remove from FormBrowser context list\r
6027 //\r
6028 RemoveEntryList (&Context->Link);\r
6029 gBS->FreePool (Context);\r
6030}\r
48a9d5f7
LG
6031\r
6032/**\r
6033 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
6034 \r
6035 @param Handle The Hii Handle.\r
6036 \r
6037 @return the found FormSet context. If no found, NULL will return.\r
6038\r
6039**/\r
6040FORM_BROWSER_FORMSET * \r
6041GetFormSetFromHiiHandle (\r
6042 EFI_HII_HANDLE Handle\r
6043 )\r
6044{\r
6045 LIST_ENTRY *Link;\r
6046 FORM_BROWSER_FORMSET *FormSet;\r
6047\r
6048 Link = GetFirstNode (&gBrowserFormSetList);\r
6049 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6050 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
6051 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6052 if (!ValidateFormSet(FormSet)) {\r
6053 continue;\r
6054 }\r
48a9d5f7
LG
6055 if (FormSet->HiiHandle == Handle) {\r
6056 return FormSet;\r
6057 }\r
48a9d5f7
LG
6058 }\r
6059 \r
6060 return NULL;\r
6061}\r
6062\r
6063/**\r
6064 Check whether the input HII handle is the FormSet that is being used.\r
6065 \r
6066 @param Handle The Hii Handle.\r
6067 \r
6068 @retval TRUE HII handle is being used.\r
6069 @retval FALSE HII handle is not being used.\r
6070\r
6071**/\r
6072BOOLEAN\r
6073IsHiiHandleInBrowserContext (\r
6074 EFI_HII_HANDLE Handle\r
6075 )\r
6076{\r
6077 LIST_ENTRY *Link;\r
6078 BROWSER_CONTEXT *Context;\r
6079\r
6080 //\r
6081 // HiiHandle is Current FormSet.\r
6082 //\r
7c6c064c 6083 if (mCurrentHiiHandle == Handle) {\r
48a9d5f7
LG
6084 return TRUE;\r
6085 }\r
6086\r
6087 //\r
6088 // Check whether HiiHandle is in BrowserContext.\r
6089 //\r
6090 Link = GetFirstNode (&gBrowserContextList);\r
6091 while (!IsNull (&gBrowserContextList, Link)) {\r
6092 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
7c6c064c 6093 if (Context->HiiHandle == Handle) {\r
48a9d5f7
LG
6094 //\r
6095 // HiiHandle is in BrowserContext\r
6096 //\r
6097 return TRUE;\r
6098 }\r
6099 Link = GetNextNode (&gBrowserContextList, Link);\r
6100 }\r
6101 \r
6102 return FALSE;\r
6103}\r
6104\r
7c6c064c
ED
6105/**\r
6106 Perform Password check. \r
6107 Passwork may be encrypted by driver that requires the specific check.\r
6108 \r
6109 @param Form Form where Password Statement is in.\r
6110 @param Statement Password statement\r
6111 @param PasswordString Password string to be checked. It may be NULL.\r
6112 NULL means to restore password.\r
6113 "" string can be used to checked whether old password does exist.\r
6114 \r
6115 @return Status Status of Password check.\r
6116**/\r
6117EFI_STATUS\r
6118EFIAPI\r
6119PasswordCheck (\r
6120 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
6121 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
6122 IN EFI_STRING PasswordString OPTIONAL\r
6123 )\r
6124{\r
6125 EFI_STATUS Status;\r
6126 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
6127 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
6128 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
6129 FORM_BROWSER_STATEMENT *Question;\r
6130\r
6131 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
6132 Question = GetBrowserStatement(Statement);\r
6133 ASSERT (Question != NULL);\r
6134\r
6135 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
6136 if (ConfigAccess == NULL) {\r
6137 return EFI_UNSUPPORTED;\r
6138 }\r
6139 } else {\r
27582c41 6140 //\r
9e2462b8 6141 // If a password doesn't have the CALLBACK flag, browser will not handle it.\r
27582c41 6142 //\r
9e2462b8 6143 return EFI_UNSUPPORTED;\r
7c6c064c
ED
6144 }\r
6145 \r
6146 //\r
6147 // Prepare password string in HII database\r
6148 //\r
6149 if (PasswordString != NULL) {\r
6150 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
6151 } else {\r
6152 IfrTypeValue.string = 0;\r
6153 }\r
6154\r
6155 //\r
6156 // Send password to Configuration Driver for validation\r
6157 //\r
6158 Status = ConfigAccess->Callback (\r
6159 ConfigAccess,\r
6160 EFI_BROWSER_ACTION_CHANGING,\r
6161 Question->QuestionId,\r
6162 Question->HiiValue.Type,\r
6163 &IfrTypeValue,\r
6164 &ActionRequest\r
6165 );\r
6166\r
6167 //\r
6168 // Remove password string from HII database\r
6169 //\r
6170 if (PasswordString != NULL) {\r
6171 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
6172 }\r
6173\r
6174 return Status;\r
6175}\r
6176\r
48a9d5f7
LG
6177/**\r
6178 Find the registered HotKey based on KeyData.\r
6179 \r
6180 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
6181 information for the hot key.\r
6182\r
6183 @return The registered HotKey context. If no found, NULL will return.\r
6184**/\r
6185BROWSER_HOT_KEY *\r
6186GetHotKeyFromRegisterList (\r
6187 IN EFI_INPUT_KEY *KeyData\r
6188 )\r
6189{\r
6190 LIST_ENTRY *Link;\r
6191 BROWSER_HOT_KEY *HotKey;\r
6192\r
6193 Link = GetFirstNode (&gBrowserHotKeyList);\r
6194 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
6195 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
6196 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
6197 return HotKey;\r
6198 }\r
6199 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
6200 }\r
6201 \r
6202 return NULL;\r
6203}\r
6204\r
6205/**\r
6206 Configure what scope the hot key will impact.\r
6207 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
6208 If no scope is set, the default scope will be FormSet level.\r
6209 After all registered hot keys are removed, previous Scope can reset to another level.\r
6210 \r
6211 @param[in] Scope Scope level to be set. \r
6212 \r
6213 @retval EFI_SUCCESS Scope is set correctly.\r
6214 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
6215 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
6216\r
6217**/\r
6218EFI_STATUS\r
6219EFIAPI\r
6220SetScope (\r
6221 IN BROWSER_SETTING_SCOPE Scope\r
6222 )\r
6223{\r
6224 if (Scope >= MaxLevel) {\r
6225 return EFI_INVALID_PARAMETER;\r
6226 }\r
7c6c064c 6227\r
48a9d5f7
LG
6228 //\r
6229 // When no hot key registered in system or on the first setting,\r
6230 // Scope can be set.\r
6231 //\r
6232 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
6233 gBrowserSettingScope = Scope;\r
6234 mBrowserScopeFirstSet = FALSE;\r
6235 } else if (Scope != gBrowserSettingScope) {\r
6236 return EFI_UNSUPPORTED;\r
6237 }\r
6238\r
6239 return EFI_SUCCESS;\r
6240}\r
6241\r
6242/**\r
6243 Register the hot key with its browser action, or unregistered the hot key.\r
6244 Only support hot key that is not printable character (control key, function key, etc.).\r
6245 If the action value is zero, the hot key will be unregistered if it has been registered.\r
6246 If the same hot key has been registered, the new action and help string will override the previous ones.\r
6247 \r
6248 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
6249 information for the hot key. Its type is EFI_INPUT_KEY to \r
6250 be supported by all ConsoleIn devices.\r
6251 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
6252 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
6253 @param[in] HelpString Help string that describes the hot key information.\r
6254 Its value may be NULL for the unregistered hot key.\r
6255 \r
6256 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
6257 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
6258 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
6259 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
291422d7 6260 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.\r
48a9d5f7
LG
6261**/\r
6262EFI_STATUS\r
6263EFIAPI\r
6264RegisterHotKey (\r
6265 IN EFI_INPUT_KEY *KeyData,\r
6266 IN UINT32 Action,\r
6267 IN UINT16 DefaultId,\r
6268 IN EFI_STRING HelpString OPTIONAL\r
6269 )\r
6270{\r
6271 BROWSER_HOT_KEY *HotKey;\r
6272\r
6273 //\r
6274 // Check input parameters.\r
6275 //\r
6276 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
6277 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
6278 return EFI_INVALID_PARAMETER;\r
6279 }\r
6280\r
6281 //\r
6282 // Check whether the input KeyData is in BrowserHotKeyList.\r
6283 //\r
6284 HotKey = GetHotKeyFromRegisterList (KeyData);\r
6285 \r
6286 //\r
6287 // Unregister HotKey\r
6288 //\r
6289 if (Action == BROWSER_ACTION_UNREGISTER) {\r
6290 if (HotKey != NULL) {\r
6291 //\r
6292 // The registered HotKey is found. \r
6293 // Remove it from List, and free its resource.\r
6294 //\r
6295 RemoveEntryList (&HotKey->Link);\r
6296 FreePool (HotKey->KeyData);\r
6297 FreePool (HotKey->HelpString);\r
6298 return EFI_SUCCESS;\r
6299 } else {\r
6300 //\r
6301 // The registered HotKey is not found. \r
6302 //\r
6303 return EFI_NOT_FOUND;\r
6304 }\r
6305 }\r
291422d7
ED
6306\r
6307 if (HotKey != NULL) {\r
6308 return EFI_ALREADY_STARTED;\r
6309 }\r
6310\r
48a9d5f7 6311 //\r
291422d7 6312 // Create new Key, and add it into List.\r
48a9d5f7 6313 //\r
291422d7
ED
6314 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
6315 ASSERT (HotKey != NULL);\r
6316 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
6317 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
6318 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
48a9d5f7
LG
6319\r
6320 //\r
6321 // Fill HotKey information.\r
6322 //\r
6323 HotKey->Action = Action;\r
6324 HotKey->DefaultId = DefaultId;\r
6325 if (HotKey->HelpString != NULL) {\r
6326 FreePool (HotKey->HelpString);\r
6327 }\r
6328 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
6329\r
6330 return EFI_SUCCESS;\r
6331}\r
6332\r
6333/**\r
6334 Register Exit handler function. \r
6335 When more than one handler function is registered, the latter one will override the previous one. \r
6336 When NULL handler is specified, the previous Exit handler will be unregistered. \r
6337 \r
6338 @param[in] Handler Pointer to handler function. \r
6339\r
6340**/\r
6341VOID\r
6342EFIAPI\r
6343RegiserExitHandler (\r
6344 IN EXIT_HANDLER Handler\r
6345 )\r
6346{\r
6347 ExitHandlerFunction = Handler;\r
6348 return;\r
6349}\r
6350\r
7c6c064c
ED
6351/**\r
6352 Check whether the browser data has been modified.\r
6353\r
6354 @retval TRUE Browser data is modified.\r
6355 @retval FALSE No browser data is modified.\r
6356\r
6357**/\r
6358BOOLEAN\r
6359EFIAPI\r
6360IsBrowserDataModified (\r
6361 VOID\r
6362 )\r
6363{\r
6364 LIST_ENTRY *Link;\r
6365 FORM_BROWSER_FORMSET *FormSet;\r
6366\r
7c6c064c
ED
6367 switch (gBrowserSettingScope) {\r
6368 case FormLevel:\r
27bace9b
ED
6369 if (gCurrentSelection == NULL) {\r
6370 return FALSE;\r
6371 }\r
7c6c064c
ED
6372 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
6373\r
6374 case FormSetLevel:\r
27bace9b
ED
6375 if (gCurrentSelection == NULL) {\r
6376 return FALSE;\r
6377 }\r
7c6c064c
ED
6378 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
6379\r
6380 case SystemLevel:\r
6381 Link = GetFirstNode (&gBrowserFormSetList);\r
6382 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6383 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
27bace9b
ED
6384 if (!ValidateFormSet(FormSet)) {\r
6385 continue;\r
6386 }\r
6387\r
7c6c064c
ED
6388 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
6389 return TRUE;\r
6390 }\r
6391 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6392 }\r
6393 return FALSE;\r
6394\r
6395 default:\r
6396 return FALSE;\r
6397 }\r
6398}\r
6399\r
6400/**\r
6401 Execute the action requested by the Action parameter.\r
6402\r
6403 @param[in] Action Execute the request action.\r
6404 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
6405\r
6406 @retval EFI_SUCCESS Execute the request action succss.\r
6407 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
6408\r
6409**/\r
6410EFI_STATUS \r
6411EFIAPI\r
6412ExecuteAction (\r
6413 IN UINT32 Action,\r
6414 IN UINT16 DefaultId\r
6415 )\r
6416{\r
27bace9b
ED
6417 EFI_STATUS Status;\r
6418 FORM_BROWSER_FORMSET *FormSet;\r
6419 FORM_BROWSER_FORM *Form;\r
7c6c064c 6420\r
27bace9b 6421 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
7c6c064c
ED
6422 return EFI_NOT_READY;\r
6423 }\r
6424\r
27bace9b
ED
6425 Status = EFI_SUCCESS;\r
6426 FormSet = NULL;\r
6427 Form = NULL;\r
6428 if (gBrowserSettingScope < SystemLevel) {\r
6429 FormSet = gCurrentSelection->FormSet;\r
6430 Form = gCurrentSelection->Form; \r
6431 }\r
7c6c064c
ED
6432\r
6433 //\r
6434 // Executet the discard action.\r
6435 //\r
6436 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
27bace9b 6437 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6438 if (EFI_ERROR (Status)) {\r
6439 return Status;\r
6440 }\r
6441 }\r
6442\r
6443 //\r
6444 // Executet the difault action.\r
6445 //\r
6446 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
787fc2a6 6447 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
7c6c064c
ED
6448 if (EFI_ERROR (Status)) {\r
6449 return Status;\r
6450 }\r
892eccc8 6451 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6452 }\r
6453\r
6454 //\r
6455 // Executet the submit action.\r
6456 //\r
6457 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
27bace9b 6458 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6459 if (EFI_ERROR (Status)) {\r
6460 return Status;\r
6461 }\r
6462 }\r
6463\r
6464 //\r
6465 // Executet the reset action.\r
6466 //\r
6467 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
6468 gResetRequired = TRUE;\r
6469 }\r
6470\r
6471 //\r
6472 // Executet the exit action.\r
6473 //\r
6474 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
27bace9b 6475 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6476 if (gBrowserSettingScope == SystemLevel) {\r
6477 if (ExitHandlerFunction != NULL) {\r
6478 ExitHandlerFunction ();\r
6479 }\r
6480 }\r
6481\r
6482 gExitRequired = TRUE;\r
6483 }\r
6484\r
6485 return Status;\r
6486}\r
6487\r
48a9d5f7
LG
6488/**\r
6489 Create reminder to let user to choose save or discard the changed browser data.\r
6490 Caller can use it to actively check the changed browser data.\r
6491\r
6492 @retval BROWSER_NO_CHANGES No browser data is changed.\r
6493 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
6494 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
27bace9b 6495 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
48a9d5f7
LG
6496\r
6497**/\r
6498UINT32\r
6499EFIAPI\r
6500SaveReminder (\r
6501 VOID\r
6502 )\r
6503{\r
6504 LIST_ENTRY *Link;\r
6505 FORM_BROWSER_FORMSET *FormSet;\r
6506 BOOLEAN IsDataChanged;\r
6507 UINT32 DataSavedAction;\r
27bace9b 6508 UINT32 ConfirmRet;\r
48a9d5f7
LG
6509\r
6510 DataSavedAction = BROWSER_NO_CHANGES;\r
6511 IsDataChanged = FALSE;\r
6512 Link = GetFirstNode (&gBrowserFormSetList);\r
6513 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6514 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
6515 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6516 if (!ValidateFormSet(FormSet)) {\r
6517 continue;\r
6518 }\r
7c6c064c 6519 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
48a9d5f7
LG
6520 IsDataChanged = TRUE;\r
6521 break;\r
6522 }\r
48a9d5f7
LG
6523 }\r
6524 \r
6525 //\r
6526 // No data is changed. No save is required. \r
6527 //\r
6528 if (!IsDataChanged) {\r
6529 return DataSavedAction;\r
6530 }\r
6531 \r
6532 //\r
7c6c064c 6533 // If data is changed, prompt user to save or discard it. \r
48a9d5f7 6534 //\r
48a9d5f7 6535 do {\r
27bace9b 6536 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
48a9d5f7 6537\r
27bace9b 6538 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
7c6c064c 6539 SubmitForm (NULL, NULL, SystemLevel);\r
27bace9b 6540 DataSavedAction = BROWSER_SAVE_CHANGES;\r
7c6c064c 6541 break;\r
27bace9b 6542 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
7c6c064c 6543 DiscardForm (NULL, NULL, SystemLevel);\r
27bace9b
ED
6544 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
6545 break;\r
6546 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
6547 DataSavedAction = BROWSER_KEEP_CURRENT;\r
7c6c064c
ED
6548 break;\r
6549 }\r
6550 } while (1);\r
48a9d5f7
LG
6551\r
6552 return DataSavedAction;\r
6553}\r
7da62bc0
ED
6554\r
6555/**\r
6556 Check whether the Reset Required for the browser\r
6557\r
6558 @retval TRUE Browser required to reset after exit.\r
6559 @retval FALSE Browser not need to reset after exit.\r
6560\r
6561**/\r
6562BOOLEAN\r
6563EFIAPI\r
6564IsResetRequired (\r
6565 VOID\r
6566 )\r
6567{\r
6568 return gResetRequired;\r
6569}\r
6570\r