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