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