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