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