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