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