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