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