]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdePkg BaseLib: Fix a corner case of Source and Destination overlap.
[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
ED
2394/**\r
2395 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2396\r
2397 @param FormSet The input FormSet which need to validate.\r
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
938baa1f 2452 if (!Find) {\r
0a6f8af5 2453 CleanBrowserStorage(FormSet);\r
938baa1f
ED
2454 RemoveEntryList (&FormSet->Link);\r
2455 DestroyFormSet (FormSet);\r
2456 }\r
2457\r
938baa1f
ED
2458 return Find;\r
2459}\r
7c6c064c
ED
2460/**\r
2461 Check whether need to enable the reset flag in form level.\r
2462 Also clean all ValueChanged flag in question.\r
2463\r
2464 @param SetFlag Whether need to set the Reset Flag.\r
4d4deaac 2465 @param FormSet FormSet data structure.\r
7c6c064c
ED
2466 @param Form Form data structure.\r
2467\r
2468**/\r
2469VOID\r
2470UpdateFlagForForm (\r
2471 IN BOOLEAN SetFlag,\r
4d4deaac 2472 IN FORM_BROWSER_FORMSET *FormSet,\r
7c6c064c
ED
2473 IN FORM_BROWSER_FORM *Form\r
2474 )\r
2475{\r
2476 LIST_ENTRY *Link;\r
2477 FORM_BROWSER_STATEMENT *Question;\r
4d4deaac 2478 BOOLEAN OldValue;\r
7c6c064c 2479\r
7c6c064c
ED
2480 Link = GetFirstNode (&Form->StatementListHead);\r
2481 while (!IsNull (&Form->StatementListHead, Link)) {\r
2482 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4d4deaac 2483 Link = GetNextNode (&Form->StatementListHead, Link);\r
7c6c064c 2484\r
4d4deaac
ED
2485 if (!Question->ValueChanged) {\r
2486 continue;\r
7c6c064c 2487 }\r
4d4deaac
ED
2488\r
2489 OldValue = Question->ValueChanged;\r
2490\r
2491 //\r
2492 // Compare the buffer and editbuffer data to see whether the data has been saved.\r
2493 //\r
2494 Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
2495\r
2496 //\r
2497 // Only the changed data has been saved, then need to set the reset flag.\r
2498 //\r
2499 if (SetFlag && OldValue && !Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
2500 gResetRequired = TRUE;\r
2501 } \r
7c6c064c
ED
2502 }\r
2503}\r
2504\r
2505/**\r
2506 Check whether need to enable the reset flag.\r
2507 Also clean ValueChanged flag for all statements.\r
2508\r
2509 Form level or formset level, only one.\r
2510 \r
2511 @param SetFlag Whether need to set the Reset Flag.\r
2512 @param FormSet FormSet data structure.\r
2513 @param Form Form data structure.\r
2514\r
2515**/\r
2516VOID\r
2517ValueChangeResetFlagUpdate (\r
2518 IN BOOLEAN SetFlag,\r
2519 IN FORM_BROWSER_FORMSET *FormSet,\r
2520 IN FORM_BROWSER_FORM *Form \r
2521 )\r
2522{\r
2523 FORM_BROWSER_FORM *CurrentForm;\r
2524 LIST_ENTRY *Link;\r
2525\r
7c6c064c 2526 if (Form != NULL) {\r
4d4deaac 2527 UpdateFlagForForm(SetFlag, FormSet, Form);\r
7c6c064c
ED
2528 return;\r
2529 }\r
2530\r
2531 Link = GetFirstNode (&FormSet->FormListHead);\r
2532 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2533 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2534 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2535\r
4d4deaac 2536 UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
7c6c064c
ED
2537 }\r
2538}\r
938baa1f 2539\r
4d4deaac
ED
2540/**\r
2541 Base on the return Progress string to find the form. \r
2542 \r
2543 Base on the first return Offset/Width (Name) string to find the form\r
2544 which keep this string.\r
2545\r
2546 @param FormSet FormSet data structure.\r
2547 @param Storage Storage which has this Progress string.\r
2548 @param Progress The Progress string which has the first fail string.\r
2549 @param RetForm The return form for this progress string.\r
2550 @param RetQuestion The return question for the error progress string.\r
2551\r
2552 @retval TRUE Find the error form and statement for this error progress string.\r
2553 @retval FALSE Not find the error form.\r
2554\r
2555**/\r
2556BOOLEAN\r
2557FindQuestionFromProgress (\r
2558 IN FORM_BROWSER_FORMSET *FormSet,\r
2559 IN BROWSER_STORAGE *Storage,\r
2560 IN EFI_STRING Progress,\r
2561 OUT FORM_BROWSER_FORM **RetForm,\r
2562 OUT FORM_BROWSER_STATEMENT **RetQuestion\r
2563 )\r
2564{\r
2565 LIST_ENTRY *Link;\r
2566 LIST_ENTRY *LinkStorage;\r
2567 LIST_ENTRY *LinkStatement;\r
2568 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2569 FORM_BROWSER_FORM *Form;\r
2570 EFI_STRING EndStr;\r
2571 FORM_BROWSER_STATEMENT *Statement;\r
2572\r
2573 ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
2574\r
2575 ConfigInfo = NULL;\r
2576 *RetForm = NULL;\r
2577 *RetQuestion = NULL;\r
2578\r
2579 //\r
2580 // Skip the first "&" or the ConfigHdr part.\r
2581 //\r
2582 if (*Progress == '&') {\r
2583 Progress++;\r
2584 } else {\r
2585 //\r
2586 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2587 //\r
2588 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2589 //\r
2590 // For Name/Value type, Skip the ConfigHdr part.\r
2591 //\r
2592 EndStr = StrStr (Progress, L"PATH=");\r
e77d2f9d 2593 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2594 while (*EndStr != '&') {\r
2595 EndStr++;\r
2596 }\r
2597\r
2598 *EndStr = '\0';\r
2599 } else {\r
2600 //\r
2601 // For Buffer type, Skip the ConfigHdr part.\r
2602 //\r
2603 EndStr = StrStr (Progress, L"&OFFSET=");\r
e77d2f9d 2604 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2605 *EndStr = '\0';\r
2606 }\r
2607\r
2608 Progress = EndStr + 1;\r
2609 }\r
2610\r
2611 //\r
2612 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2613 //\r
2614 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2615 //\r
2616 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2617 // here, just keep the "Fred" string.\r
2618 //\r
2619 EndStr = StrStr (Progress, L"=");\r
e77d2f9d 2620 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2621 *EndStr = '\0';\r
2622 } else {\r
2623 //\r
2624 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2625 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2626 //\r
2627 EndStr = StrStr (Progress, L"&VALUE=");\r
e77d2f9d 2628 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2629 *EndStr = '\0';\r
2630 }\r
2631\r
2632 //\r
2633 // Search in the form list.\r
2634 //\r
2635 Link = GetFirstNode (&FormSet->FormListHead);\r
2636 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2637 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2638 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2639\r
2640 //\r
2641 // Search in the ConfigReqeust list in this form.\r
2642 //\r
2643 LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
2644 while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
2645 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
2646 LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
2647\r
2648 if (Storage != ConfigInfo->Storage) {\r
2649 continue;\r
2650 }\r
2651\r
2652 if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
2653 //\r
2654 // Find the OffsetWidth string in this form.\r
2655 //\r
2656 *RetForm = Form;\r
2657 break;\r
2658 }\r
2659 }\r
2660\r
2661 if (*RetForm != NULL) {\r
2662 LinkStatement = GetFirstNode (&Form->StatementListHead);\r
2663 while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
2664 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
2665 LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
2666\r
2667 if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
2668 *RetQuestion = Statement;\r
2669 break;\r
2670 }\r
2671 }\r
2672 }\r
2673\r
2674 if (*RetForm != NULL) {\r
2675 break;\r
2676 }\r
2677 }\r
2678\r
2679 //\r
2680 // restore the OffsetWidth string to the original format.\r
2681 //\r
2682 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2683 *EndStr = '=';\r
2684 } else {\r
2685 *EndStr = '&';\r
2686 }\r
2687\r
5039b444 2688 return (BOOLEAN) (*RetForm != NULL);\r
4d4deaac
ED
2689}\r
2690\r
2691/**\r
2692 Popup an save error info and get user input.\r
2693\r
2694 @param TitleId The form title id.\r
2695 @param HiiHandle The hii handle for this package.\r
2696\r
2697 @retval UINT32 The user select option for the save fail.\r
2698 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2699**/\r
2700UINT32\r
2701ConfirmSaveFail (\r
2702 IN EFI_STRING_ID TitleId,\r
2703 IN EFI_HII_HANDLE HiiHandle\r
2704 )\r
2705{\r
2706 CHAR16 *FormTitle;\r
2707 CHAR16 *StringBuffer;\r
2708 UINT32 RetVal;\r
2709\r
2710 FormTitle = GetToken (TitleId, HiiHandle);\r
2711\r
2712 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2713 ASSERT (StringBuffer != NULL);\r
2714\r
2715 UnicodeSPrint (\r
2716 StringBuffer, \r
2717 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2718 L"Submit Fail For Form: %s.", \r
2719 FormTitle\r
2720 );\r
2721\r
2722 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
2723\r
2724 FreePool (StringBuffer);\r
2725 FreePool (FormTitle);\r
2726\r
2727 return RetVal;\r
2728}\r
2729\r
2730/**\r
2731 Popup an NO_SUBMIT_IF error info and get user input.\r
2732\r
2733 @param TitleId The form title id.\r
2734 @param HiiHandle The hii handle for this package.\r
2735\r
2736 @retval UINT32 The user select option for the save fail.\r
2737 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2738**/\r
2739UINT32\r
2740ConfirmNoSubmitFail (\r
2741 IN EFI_STRING_ID TitleId,\r
2742 IN EFI_HII_HANDLE HiiHandle\r
2743 )\r
2744{\r
2745 CHAR16 *FormTitle;\r
2746 CHAR16 *StringBuffer;\r
2747 UINT32 RetVal;\r
2748\r
2749 FormTitle = GetToken (TitleId, HiiHandle);\r
2750\r
2751 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2752 ASSERT (StringBuffer != NULL);\r
2753\r
2754 UnicodeSPrint (\r
2755 StringBuffer, \r
2756 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2757 L"NO_SUBMIT_IF error For Form: %s.", \r
2758 FormTitle\r
2759 );\r
2760\r
2761 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
2762\r
2763 FreePool (StringBuffer);\r
2764 FreePool (FormTitle);\r
2765\r
2766 return RetVal;\r
2767}\r
2768\r
b18e7050 2769/**\r
48a9d5f7 2770 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 2771\r
2772 @param FormSet FormSet data structure.\r
2773 @param Form Form data structure.\r
48a9d5f7 2774 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
2775\r
2776 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2777 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
2778\r
2779**/\r
2780EFI_STATUS\r
2781DiscardForm (\r
2782 IN FORM_BROWSER_FORMSET *FormSet,\r
2783 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2784 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
2785 )\r
2786{\r
48a9d5f7
LG
2787 LIST_ENTRY *Link;\r
2788 FORMSET_STORAGE *Storage;\r
b18e7050 2789 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
6e74560f
ED
2790 FORM_BROWSER_FORMSET *LocalFormSet;\r
2791 FORM_BROWSER_FORMSET *OldFormSet;\r
b18e7050 2792\r
48a9d5f7
LG
2793 //\r
2794 // Check the supported setting level.\r
2795 //\r
2796 if (SettingScope >= MaxLevel) {\r
2797 return EFI_UNSUPPORTED;\r
2798 }\r
b18e7050 2799\r
7c6c064c 2800 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
48a9d5f7
LG
2801 ConfigInfo = NULL;\r
2802 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2803 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2804 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2805 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 2806\r
48a9d5f7
LG
2807 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2808 continue;\r
2809 }\r
2810\r
2811 //\r
2812 // Skip if there is no RequestElement\r
2813 //\r
2814 if (ConfigInfo->ElementCount == 0) {\r
2815 continue;\r
b18e7050
ED
2816 }\r
2817\r
48a9d5f7
LG
2818 //\r
2819 // Prepare <ConfigResp>\r
2820 //\r
4d4deaac 2821 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
816a7110 2822\r
816a7110
ED
2823 //\r
2824 // Call callback with Changed type to inform the driver.\r
2825 //\r
2826 SendDiscardInfoToDriver (FormSet, Form);\r
2827 }\r
2828\r
4d4deaac 2829 ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
7c6c064c 2830 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
f1660263 2831\r
48a9d5f7
LG
2832 //\r
2833 // Discard Buffer storage or Name/Value storage\r
2834 //\r
2835 Link = GetFirstNode (&FormSet->StorageListHead);\r
2836 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2837 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2838 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2839\r
94f3aae7 2840 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
48a9d5f7
LG
2841 continue;\r
2842 }\r
2843\r
b18e7050 2844 //\r
48a9d5f7 2845 // Skip if there is no RequestElement\r
b18e7050 2846 //\r
48a9d5f7
LG
2847 if (Storage->ElementCount == 0) {\r
2848 continue;\r
2849 }\r
b18e7050 2850\r
4d4deaac 2851 SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
48a9d5f7 2852 }\r
f1660263
ED
2853\r
2854 Link = GetFirstNode (&FormSet->FormListHead);\r
2855 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2856 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2857 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2858 \r
2859 //\r
2860 // Call callback with Changed type to inform the driver.\r
2861 //\r
2862 SendDiscardInfoToDriver (FormSet, Form);\r
2863 }\r
b18e7050 2864\r
7c6c064c 2865 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
48a9d5f7
LG
2866 } else if (SettingScope == SystemLevel) {\r
2867 //\r
2868 // System Level Discard.\r
2869 //\r
6e74560f
ED
2870 OldFormSet = mSystemLevelFormSet;\r
2871\r
48a9d5f7
LG
2872 //\r
2873 // Discard changed value for each FormSet in the maintain list.\r
2874 //\r
2875 Link = GetFirstNode (&gBrowserFormSetList);\r
2876 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2877 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 2878 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
2879 if (!ValidateFormSet(LocalFormSet)) {\r
2880 continue;\r
2881 }\r
6e74560f
ED
2882\r
2883 mSystemLevelFormSet = LocalFormSet;\r
2884\r
938baa1f 2885 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7 2886 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 2887 //\r
48a9d5f7 2888 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 2889 //\r
0a6f8af5 2890 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
2891 RemoveEntryList (&LocalFormSet->Link);\r
2892 DestroyFormSet (LocalFormSet);\r
b18e7050 2893 }\r
b18e7050 2894 }\r
6e74560f
ED
2895\r
2896 mSystemLevelFormSet = OldFormSet;\r
b18e7050
ED
2897 }\r
2898\r
2899 return EFI_SUCCESS; \r
2900}\r
2901\r
2902/**\r
4d4deaac 2903 Submit data for a form.\r
b18e7050
ED
2904\r
2905 @param FormSet FormSet data structure.\r
2906 @param Form Form data structure.\r
7936fb6a 2907\r
2908 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2909 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2910\r
2911**/\r
2912EFI_STATUS\r
4d4deaac 2913SubmitForForm (\r
7936fb6a 2914 IN FORM_BROWSER_FORMSET *FormSet,\r
4d4deaac 2915 IN FORM_BROWSER_FORM *Form\r
7936fb6a 2916 )\r
2917{\r
2918 EFI_STATUS Status;\r
2919 LIST_ENTRY *Link;\r
2920 EFI_STRING ConfigResp;\r
2921 EFI_STRING Progress;\r
94f3aae7 2922 BROWSER_STORAGE *Storage;\r
b18e7050 2923 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 2924\r
4d4deaac
ED
2925 if (!IsNvUpdateRequiredForForm (Form)) {\r
2926 return EFI_SUCCESS;\r
2927 }\r
2928\r
2929 Status = NoSubmitCheck (FormSet, &Form, NULL);\r
2930 if (EFI_ERROR (Status)) {\r
2931 return Status;\r
2932 }\r
2933\r
2934 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2935 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2936 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2937 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
2938\r
2939 Storage = ConfigInfo->Storage;\r
2940 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2941 continue;\r
2942 }\r
2943\r
2944 //\r
2945 // Skip if there is no RequestElement\r
2946 //\r
2947 if (ConfigInfo->ElementCount == 0) {\r
2948 continue;\r
2949 }\r
2950\r
2951 //\r
2952 // 1. Prepare <ConfigResp>\r
2953 //\r
2954 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
2955 if (EFI_ERROR (Status)) {\r
2956 return Status;\r
2957 }\r
2958\r
2959 //\r
2960 // 2. Set value to hii config routine protocol.\r
2961 //\r
2962 Status = mHiiConfigRouting->RouteConfig (\r
2963 mHiiConfigRouting,\r
2964 ConfigResp,\r
2965 &Progress\r
2966 );\r
2967 FreePool (ConfigResp);\r
2968\r
2969 if (EFI_ERROR (Status)) {\r
2970 InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
2971 continue;\r
2972 }\r
2973\r
2974 //\r
2975 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
2976 //\r
2977 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
2978 }\r
2979\r
48a9d5f7 2980 //\r
4d4deaac 2981 // 4. Process the save failed storage.\r
48a9d5f7 2982 //\r
4d4deaac
ED
2983 if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
2984 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
2985 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
2986 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
2987 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
2988 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
2989\r
2990 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
2991\r
2992 Status = EFI_SUCCESS;\r
2993 }\r
2994 } else {\r
2995 Status = EFI_UNSUPPORTED;\r
2996 }\r
2997\r
2998 //\r
2999 // Free Form save fail list.\r
3000 //\r
3001 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3002 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3003 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3004 RemoveEntryList (&ConfigInfo->SaveFailLink);\r
3005 }\r
48a9d5f7
LG
3006 }\r
3007\r
7936fb6a 3008 //\r
4d4deaac 3009 // 5. Update the NV flag.\r
7936fb6a 3010 //\r
4d4deaac
ED
3011 ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
3012\r
3013 return Status;\r
3014}\r
3015\r
3016/**\r
3017 Submit data for a formset.\r
3018\r
3019 @param FormSet FormSet data structure.\r
3020 @param SkipProcessFail Whether skip to process the save failed storage.\r
3021 If submit formset is called when do system level save, \r
3022 set this value to true and process the failed formset \r
3023 together. \r
3024 if submit formset is called when do formset level save,\r
3025 set the value to false and process the failed storage\r
3026 right after process all storages for this formset.\r
3027\r
3028 @retval EFI_SUCCESS The function completed successfully.\r
3029 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3030\r
3031**/\r
3032EFI_STATUS\r
3033SubmitForFormSet (\r
3034 IN FORM_BROWSER_FORMSET *FormSet,\r
3035 IN BOOLEAN SkipProcessFail\r
3036 )\r
3037{\r
3038 EFI_STATUS Status;\r
3039 LIST_ENTRY *Link;\r
3040 EFI_STRING ConfigResp;\r
3041 EFI_STRING Progress;\r
3042 BROWSER_STORAGE *Storage;\r
3043 FORMSET_STORAGE *FormSetStorage;\r
3044 FORM_BROWSER_FORM *Form;\r
3045 BOOLEAN HasInserted;\r
3046 FORM_BROWSER_STATEMENT *Question;\r
3047\r
3048 HasInserted = FALSE;\r
3049\r
3050 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
3051 return EFI_SUCCESS;\r
b18e7050 3052 }\r
4d4deaac
ED
3053\r
3054 Form = NULL; \r
3055 Status = NoSubmitCheck (FormSet, &Form, &Question);\r
7936fb6a 3056 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
3057 if (SkipProcessFail) {\r
3058 //\r
3059 // Process NO_SUBMIT check first, so insert it at head.\r
3060 //\r
3061 FormSet->SaveFailForm = Form;\r
3062 FormSet->SaveFailStatement = Question;\r
3063 InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3064 }\r
3065\r
7936fb6a 3066 return Status;\r
3067 }\r
3068\r
4d4deaac
ED
3069 Form = NULL;\r
3070 Question = NULL;\r
3071 //\r
3072 // Submit Buffer storage or Name/Value storage\r
3073 //\r
3074 Link = GetFirstNode (&FormSet->StorageListHead);\r
3075 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3076 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3077 Storage = FormSetStorage->BrowserStorage;\r
3078 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
7936fb6a 3079\r
4d4deaac
ED
3080 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3081 continue;\r
3082 }\r
7936fb6a 3083\r
4d4deaac
ED
3084 //\r
3085 // Skip if there is no RequestElement\r
3086 //\r
3087 if (FormSetStorage->ElementCount == 0) {\r
3088 continue;\r
3089 }\r
7936fb6a 3090\r
4d4deaac
ED
3091 //\r
3092 // 1. Prepare <ConfigResp>\r
3093 //\r
3094 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
3095 if (EFI_ERROR (Status)) {\r
3096 return Status;\r
3097 }\r
b18e7050 3098\r
4d4deaac
ED
3099 //\r
3100 // 2. Send <ConfigResp> to Routine config Protocol.\r
3101 //\r
3102 Status = mHiiConfigRouting->RouteConfig (\r
3103 mHiiConfigRouting,\r
3104 ConfigResp,\r
3105 &Progress\r
3106 );\r
3107 if (EFI_ERROR (Status)) {\r
3108 InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
3109 if (!HasInserted) {\r
3110 //\r
3111 // Call submit formset for system level, save the formset info\r
3112 // and process later.\r
3113 //\r
3114 FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
3115 ASSERT (Form != NULL && Question != NULL);\r
3116 FormSet->SaveFailForm = Form;\r
3117 FormSet->SaveFailStatement = Question;\r
3118 if (SkipProcessFail) {\r
3119 InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3120 }\r
3121 HasInserted = TRUE;\r
b18e7050 3122 }\r
7248790e 3123\r
b18e7050 3124 FreePool (ConfigResp);\r
4d4deaac 3125 continue;\r
7936fb6a 3126 }\r
3127\r
4d4deaac 3128 FreePool (ConfigResp);\r
cce6230f 3129 //\r
4d4deaac 3130 // 3. Config success, update storage shadow Buffer\r
7936fb6a 3131 //\r
4d4deaac
ED
3132 SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
3133 }\r
b18e7050 3134\r
4d4deaac
ED
3135 //\r
3136 // 4. Has save fail storage need to handle.\r
3137 //\r
3138 if (Form != NULL) {\r
3139 if (!SkipProcessFail) {\r
b18e7050 3140 //\r
4d4deaac 3141 // If not in system level, just handl the save failed storage here.\r
b18e7050 3142 //\r
4d4deaac
ED
3143 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3144 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3145 while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
3146 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3147 Storage = FormSetStorage->BrowserStorage;\r
3148 Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
b18e7050 3149\r
4d4deaac
ED
3150 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3151\r
3152 Status = EFI_SUCCESS;\r
3153 }\r
3154 } else {\r
3155 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3156\r
3157 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3158 gCurrentSelection->Handle = FormSet->HiiHandle;\r
3159 CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
3160 gCurrentSelection->FormId = Form->FormId;\r
3161 gCurrentSelection->QuestionId = Question->QuestionId;\r
3162\r
3163 Status = EFI_UNSUPPORTED;\r
7936fb6a 3164 }\r
b18e7050 3165\r
7248790e 3166 //\r
4d4deaac 3167 // Free FormSet save fail list.\r
7248790e 3168 //\r
4d4deaac
ED
3169 while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
3170 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3171 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3172 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
b18e7050 3173 }\r
4d4deaac 3174 } else {\r
b18e7050 3175 //\r
4d4deaac 3176 // If in system level, just return error and handle the failed formset later.\r
b18e7050 3177 //\r
4d4deaac
ED
3178 Status = EFI_UNSUPPORTED;\r
3179 }\r
3180 }\r
3181\r
3182 //\r
3183 // 5. Update the NV flag.\r
3184 // \r
3185 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
3186\r
3187 return Status;\r
3188}\r
3189\r
3190/**\r
3191 Submit data for all formsets.\r
3192\r
3193 @retval EFI_SUCCESS The function completed successfully.\r
3194 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3195\r
3196**/\r
3197EFI_STATUS\r
3198SubmitForSystem (\r
3199 VOID\r
3200 )\r
3201{\r
3202 EFI_STATUS Status;\r
3203 LIST_ENTRY *Link;\r
3204 LIST_ENTRY *StorageLink;\r
3205 BROWSER_STORAGE *Storage;\r
3206 FORMSET_STORAGE *FormSetStorage;\r
3207 FORM_BROWSER_FORM *Form;\r
3208 FORM_BROWSER_FORMSET *LocalFormSet;\r
3209 UINT32 UserSelection;\r
3210 FORM_BROWSER_STATEMENT *Question;\r
3211\r
3212 mSystemSubmit = TRUE;\r
3213 Link = GetFirstNode (&gBrowserFormSetList);\r
3214 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3215 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3216 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3217 if (!ValidateFormSet(LocalFormSet)) {\r
3218 continue;\r
3219 }\r
3220\r
3221 Status = SubmitForFormSet (LocalFormSet, TRUE);\r
3222 if (EFI_ERROR (Status)) {\r
3223 continue;\r
7936fb6a 3224 }\r
7936fb6a 3225\r
cce6230f 3226 //\r
4d4deaac
ED
3227 // Remove maintain backup list after save except for the current using FormSet.\r
3228 // \r
3229 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3230 CleanBrowserStorage(LocalFormSet);\r
3231 RemoveEntryList (&LocalFormSet->Link);\r
3232 DestroyFormSet (LocalFormSet);\r
3233 }\r
3234 }\r
3235 mSystemSubmit = FALSE;\r
3236\r
3237 Status = EFI_SUCCESS;\r
3238\r
3239 //\r
3240 // Process the save failed formsets.\r
3241 //\r
3242 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3243 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3244 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3245 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3246\r
3247 if (!ValidateFormSet(LocalFormSet)) {\r
3248 continue;\r
3249 }\r
3250\r
3251 Form = LocalFormSet->SaveFailForm;\r
3252 Question= LocalFormSet->SaveFailStatement;\r
48a9d5f7
LG
3253\r
3254 //\r
4d4deaac 3255 // Confirm with user, get user input.\r
48a9d5f7 3256 //\r
4d4deaac
ED
3257 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3258 //\r
3259 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
3260 //\r
3261 UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3262 } else {\r
3263 UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3264 }\r
3265\r
3266 if (UserSelection == BROWSER_ACTION_DISCARD) {\r
3267 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3268 StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
3269 while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
3270 FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
3271 Storage = FormSetStorage->BrowserStorage;\r
3272 StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
3273\r
3274 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3275 }\r
3276 } else {\r
3277 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3278 while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
3279 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3280 Storage = FormSetStorage->BrowserStorage;\r
3281 StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
3282\r
3283 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3284 }\r
938baa1f 3285 }\r
4d4deaac 3286\r
48a9d5f7 3287 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
0a6f8af5 3288 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7 3289 RemoveEntryList (&LocalFormSet->Link);\r
4d4deaac 3290 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
48a9d5f7 3291 DestroyFormSet (LocalFormSet);\r
4d4deaac
ED
3292 } else {\r
3293 ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
48a9d5f7 3294 }\r
4d4deaac
ED
3295 } else {\r
3296 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3297 NoSubmitCheck (LocalFormSet, &Form, &Question);\r
3298 }\r
3299\r
3300 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3301\r
3302 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3303 gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
3304 CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
3305 gCurrentSelection->FormId = Form->FormId;\r
3306 gCurrentSelection->QuestionId = Question->QuestionId;\r
3307\r
3308 Status = EFI_UNSUPPORTED;\r
3309 break;\r
48a9d5f7 3310 }\r
7936fb6a 3311 }\r
3312\r
4d4deaac
ED
3313 //\r
3314 // Clean the list which will not process.\r
3315 //\r
3316 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3317 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3318 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3319 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3320\r
3321 while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3322 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3323 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3324 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3325 }\r
3326 }\r
3327\r
3328 return Status;\r
3329}\r
3330\r
3331/**\r
3332 Submit data based on the input Setting level (Form, FormSet or System).\r
3333\r
3334 @param FormSet FormSet data structure.\r
3335 @param Form Form data structure.\r
3336 @param SettingScope Setting Scope for Submit action.\r
3337\r
3338 @retval EFI_SUCCESS The function completed successfully.\r
3339 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3340\r
3341**/\r
3342EFI_STATUS\r
3343SubmitForm (\r
3344 IN FORM_BROWSER_FORMSET *FormSet,\r
3345 IN FORM_BROWSER_FORM *Form,\r
3346 IN BROWSER_SETTING_SCOPE SettingScope\r
3347 )\r
3348{\r
3349 EFI_STATUS Status;\r
3350\r
3351 switch (SettingScope) {\r
3352 case FormLevel:\r
3353 Status = SubmitForForm(FormSet, Form);\r
3354 break;\r
3355\r
3356 case FormSetLevel:\r
3357 Status = SubmitForFormSet (FormSet, FALSE);\r
3358 break;\r
3359\r
3360 case SystemLevel:\r
3361 Status = SubmitForSystem ();\r
3362 break;\r
3363\r
3364 default:\r
3365 Status = EFI_UNSUPPORTED;\r
3366 break;\r
3367 }\r
3368\r
3369 return Status;\r
7936fb6a 3370}\r
3371\r
ee31d1be
ED
3372/**\r
3373 Get Question default value from AltCfg string.\r
3374\r
3375 @param FormSet The form set.\r
3376 @param Question The question.\r
3377 @param DefaultId The default Id.\r
3378\r
3379 @retval EFI_SUCCESS Question is reset to default value.\r
3380\r
3381**/\r
3382EFI_STATUS\r
3383GetDefaultValueFromAltCfg (\r
3384 IN FORM_BROWSER_FORMSET *FormSet,\r
3385 IN OUT FORM_BROWSER_STATEMENT *Question,\r
3386 IN UINT16 DefaultId\r
3387 )\r
3388{\r
3389 BOOLEAN IsBufferStorage;\r
3390 BOOLEAN IsString; \r
3391 UINTN Length;\r
94f3aae7 3392 BROWSER_STORAGE *Storage;\r
ee31d1be
ED
3393 CHAR16 *ConfigRequest;\r
3394 CHAR16 *Progress;\r
3395 CHAR16 *Result;\r
3396 CHAR16 *ConfigResp;\r
3397 CHAR16 *Value;\r
3398 CHAR16 *StringPtr;\r
3399 UINTN LengthStr;\r
3400 UINT8 *Dst;\r
3401 CHAR16 TemStr[5];\r
3402 UINTN Index;\r
3403 UINT8 DigitUint8;\r
3404 EFI_STATUS Status;\r
3405\r
3406 Status = EFI_NOT_FOUND;\r
3407 Length = 0;\r
3408 Dst = NULL;\r
3409 ConfigRequest = NULL;\r
3410 Result = NULL;\r
3411 ConfigResp = NULL;\r
0194d26c 3412 Value = NULL;\r
ee31d1be
ED
3413 Storage = Question->Storage;\r
3414\r
7248790e 3415 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
ee31d1be
ED
3416 return Status;\r
3417 }\r
3418\r
3419 //\r
3420 // Question Value is provided by Buffer Storage or NameValue Storage\r
3421 //\r
3422 if (Question->BufferValue != NULL) {\r
3423 //\r
3424 // This Question is password or orderedlist\r
3425 //\r
3426 Dst = Question->BufferValue;\r
3427 } else {\r
3428 //\r
3429 // Other type of Questions\r
3430 //\r
3431 Dst = (UINT8 *) &Question->HiiValue.Value;\r
3432 }\r
3433\r
7248790e
ED
3434 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
3435 IsBufferStorage = TRUE;\r
3436 } else {\r
3437 IsBufferStorage = FALSE;\r
3438 }\r
ee31d1be
ED
3439 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
3440\r
3441 //\r
3442 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
3443 // <ConfigHdr> + "&" + <VariableName>\r
3444 //\r
3445 if (IsBufferStorage) {\r
3446 Length = StrLen (Storage->ConfigHdr);\r
3447 Length += StrLen (Question->BlockName);\r
3448 } else {\r
3449 Length = StrLen (Storage->ConfigHdr);\r
3450 Length += StrLen (Question->VariableName) + 1;\r
3451 }\r
3452 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
3453 ASSERT (ConfigRequest != NULL);\r
3454\r
3455 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
3456 if (IsBufferStorage) {\r
3457 StrCat (ConfigRequest, Question->BlockName);\r
3458 } else {\r
3459 StrCat (ConfigRequest, L"&");\r
3460 StrCat (ConfigRequest, Question->VariableName);\r
3461 }\r
3462\r
7248790e
ED
3463 Status = mHiiConfigRouting->ExtractConfig (\r
3464 mHiiConfigRouting,\r
ee31d1be
ED
3465 ConfigRequest,\r
3466 &Progress,\r
3467 &Result\r
3468 );\r
3469 if (EFI_ERROR (Status)) {\r
3470 goto Done;\r
3471 }\r
3472\r
3473 //\r
3474 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
3475 // Get the default configuration string according to the default ID.\r
3476 //\r
3477 Status = mHiiConfigRouting->GetAltConfig (\r
3478 mHiiConfigRouting,\r
3479 Result,\r
3480 &Storage->Guid,\r
3481 Storage->Name,\r
3482 NULL,\r
3483 &DefaultId, // it can be NULL to get the current setting.\r
3484 &ConfigResp\r
3485 );\r
3486 \r
3487 //\r
3488 // The required setting can't be found. So, it is not required to be validated and set.\r
3489 //\r
3490 if (EFI_ERROR (Status)) {\r
3491 goto Done;\r
3492 }\r
3493\r
7248790e
ED
3494 if (ConfigResp == NULL) {\r
3495 Status = EFI_NOT_FOUND;\r
3496 goto Done;\r
3497 }\r
3498\r
ee31d1be
ED
3499 //\r
3500 // Skip <ConfigRequest>\r
3501 //\r
ee31d1be 3502 if (IsBufferStorage) {\r
0194d26c
ED
3503 Value = StrStr (ConfigResp, L"&VALUE");\r
3504 ASSERT (Value != NULL);\r
ee31d1be
ED
3505 //\r
3506 // Skip "&VALUE"\r
3507 //\r
3508 Value = Value + 6;\r
0194d26c
ED
3509 } else {\r
3510 Value = StrStr (ConfigResp, Question->VariableName);\r
3511 ASSERT (Value != NULL);\r
3512\r
3513 Value = Value + StrLen (Question->VariableName);\r
ee31d1be
ED
3514 }\r
3515 if (*Value != '=') {\r
3516 Status = EFI_NOT_FOUND;\r
3517 goto Done;\r
3518 }\r
3519 //\r
3520 // Skip '=', point to value\r
3521 //\r
3522 Value = Value + 1;\r
3523\r
3524 //\r
3525 // Suppress <AltResp> if any\r
3526 //\r
3527 StringPtr = Value;\r
3528 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3529 StringPtr++;\r
3530 }\r
3531 *StringPtr = L'\0';\r
3532\r
3533 LengthStr = StrLen (Value);\r
3534 if (!IsBufferStorage && IsString) {\r
3535 StringPtr = (CHAR16 *) Dst;\r
3536 ZeroMem (TemStr, sizeof (TemStr));\r
3537 for (Index = 0; Index < LengthStr; Index += 4) {\r
3538 StrnCpy (TemStr, Value + Index, 4);\r
3539 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
3540 }\r
3541 //\r
3542 // Add tailing L'\0' character\r
3543 //\r
25361615
ED
3544 StringPtr[Index/4] = L'\0';\r
3545 } else {\r
3546 ZeroMem (TemStr, sizeof (TemStr));\r
3547 for (Index = 0; Index < LengthStr; Index ++) {\r
3548 TemStr[0] = Value[LengthStr - Index - 1];\r
3549 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
3550 if ((Index & 1) == 0) {\r
3551 Dst [Index/2] = DigitUint8;\r
3552 } else {\r
3553 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
3554 }\r
3555 }\r
3556 }\r
b9feb4bd 3557\r
7c6c064c
ED
3558Done:\r
3559 if (ConfigRequest != NULL){\r
3560 FreePool (ConfigRequest);\r
3561 }\r
3562\r
3563 if (ConfigResp != NULL) {\r
3564 FreePool (ConfigResp);\r
3565 }\r
3566 \r
3567 if (Result != NULL) {\r
3568 FreePool (Result);\r
3569 }\r
3570\r
3571 return Status;\r
3572}\r
3573\r
3574/**\r
3575 Get default Id value used for browser.\r
3576\r
3577 @param DefaultId The default id value used by hii.\r
3578\r
3579 @retval Browser used default value.\r
3580\r
3581**/\r
3582INTN\r
3583GetDefaultIdForCallBack (\r
3584 UINTN DefaultId\r
3585 )\r
3586{ \r
3587 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3588 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
3589 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3590 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
3591 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
3592 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
3593 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
3594 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
3595 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
3596 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
3597 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
3598 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
3599 } else {\r
3600 return -1;\r
3601 }\r
3602}\r
3603\r
3604\r
3605\r
3606/**\r
3607 Return data element in an Array by its Index.\r
3608\r
3609 @param Array The data array.\r
3610 @param Type Type of the data in this array.\r
3611 @param Index Zero based index for data in this array.\r
3612\r
3613 @retval Value The data to be returned\r
3614\r
3615**/\r
3616UINT64\r
3617GetArrayData (\r
3618 IN VOID *Array,\r
3619 IN UINT8 Type,\r
3620 IN UINTN Index\r
3621 )\r
3622{\r
3623 UINT64 Data;\r
3624\r
3625 ASSERT (Array != NULL);\r
3626\r
3627 Data = 0;\r
3628 switch (Type) {\r
3629 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3630 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
3631 break;\r
3632\r
3633 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3634 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
3635 break;\r
3636\r
3637 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3638 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
3639 break;\r
3640\r
3641 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3642 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
3643 break;\r
3644\r
3645 default:\r
3646 break;\r
3647 }\r
3648\r
3649 return Data;\r
3650}\r
3651\r
3652\r
3653/**\r
3654 Set value of a data element in an Array by its Index.\r
3655\r
3656 @param Array The data array.\r
3657 @param Type Type of the data in this array.\r
3658 @param Index Zero based index for data in this array.\r
3659 @param Value The value to be set.\r
3660\r
3661**/\r
3662VOID\r
3663SetArrayData (\r
3664 IN VOID *Array,\r
3665 IN UINT8 Type,\r
3666 IN UINTN Index,\r
3667 IN UINT64 Value\r
3668 )\r
3669{\r
3670\r
3671 ASSERT (Array != NULL);\r
b9feb4bd 3672\r
7c6c064c
ED
3673 switch (Type) {\r
3674 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3675 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
3676 break;\r
25361615 3677\r
7c6c064c
ED
3678 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3679 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
3680 break;\r
3681\r
3682 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3683 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
3684 break;\r
3685\r
3686 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3687 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
3688 break;\r
3689\r
3690 default:\r
3691 break;\r
3692 }\r
ee31d1be
ED
3693}\r
3694\r
3695/**\r
7c6c064c 3696 Search an Option of a Question by its value.\r
ee31d1be 3697\r
7c6c064c
ED
3698 @param Question The Question\r
3699 @param OptionValue Value for Option to be searched.\r
ee31d1be 3700\r
7c6c064c
ED
3701 @retval Pointer Pointer to the found Option.\r
3702 @retval NULL Option not found.\r
ee31d1be
ED
3703\r
3704**/\r
7c6c064c
ED
3705QUESTION_OPTION *\r
3706ValueToOption (\r
3707 IN FORM_BROWSER_STATEMENT *Question,\r
3708 IN EFI_HII_VALUE *OptionValue\r
ee31d1be 3709 )\r
7c6c064c
ED
3710{\r
3711 LIST_ENTRY *Link;\r
3712 QUESTION_OPTION *Option;\r
3713 INTN Result;\r
3714\r
3715 Link = GetFirstNode (&Question->OptionListHead);\r
3716 while (!IsNull (&Question->OptionListHead, Link)) {\r
3717 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3718\r
3719 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
3720 //\r
3721 // Check the suppressif condition, only a valid option can be return.\r
3722 //\r
3723 if ((Option->SuppressExpression == NULL) ||\r
3724 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
3725 return Option;\r
3726 }\r
3727 }\r
3728\r
3729 Link = GetNextNode (&Question->OptionListHead, Link);\r
ee31d1be 3730 }\r
7c6c064c
ED
3731\r
3732 return NULL;\r
ee31d1be 3733}\r
7936fb6a 3734\r
7c6c064c 3735\r
7936fb6a 3736/**\r
3737 Reset Question to its default value.\r
3738\r
3739 @param FormSet The form set.\r
3740 @param Form The form.\r
3741 @param Question The question.\r
3742 @param DefaultId The Class of the default.\r
3743\r
3744 @retval EFI_SUCCESS Question is reset to default value.\r
3745\r
3746**/\r
3747EFI_STATUS\r
3748GetQuestionDefault (\r
3749 IN FORM_BROWSER_FORMSET *FormSet,\r
3750 IN FORM_BROWSER_FORM *Form,\r
3751 IN FORM_BROWSER_STATEMENT *Question,\r
3752 IN UINT16 DefaultId\r
3753 )\r
3754{\r
3755 EFI_STATUS Status;\r
3756 LIST_ENTRY *Link;\r
3757 QUESTION_DEFAULT *Default;\r
3758 QUESTION_OPTION *Option;\r
3759 EFI_HII_VALUE *HiiValue;\r
3760 UINT8 Index;\r
086cd2c8 3761 EFI_STRING StrValue;\r
ee31d1be
ED
3762 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3763 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
3764 INTN Action;\r
061d5462 3765 CHAR16 *NewString;\r
7936fb6a 3766\r
48a9d5f7 3767 Status = EFI_NOT_FOUND;\r
086cd2c8 3768 StrValue = NULL;\r
7936fb6a 3769\r
3770 //\r
3771 // Statement don't have storage, skip them\r
3772 //\r
3773 if (Question->QuestionId == 0) {\r
3774 return Status;\r
3775 }\r
3776\r
3777 //\r
ee31d1be
ED
3778 // There are Five ways to specify default value for a Question:\r
3779 // 1, use call back function (highest priority)\r
3780 // 2, use ExtractConfig function\r
3781 // 3, use nested EFI_IFR_DEFAULT \r
3782 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
3783 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 3784 //\r
3785 HiiValue = &Question->HiiValue;\r
3786\r
ee31d1be
ED
3787 //\r
3788 // Get Question defaut value from call back function.\r
3789 //\r
3790 ConfigAccess = FormSet->ConfigAccess;\r
3791 Action = GetDefaultIdForCallBack (DefaultId);\r
3792 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
3793 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
3794 Status = ConfigAccess->Callback (\r
3795 ConfigAccess,\r
3796 Action,\r
3797 Question->QuestionId,\r
3798 HiiValue->Type,\r
3799 &HiiValue->Value,\r
3800 &ActionRequest\r
3801 );\r
3802 if (!EFI_ERROR (Status)) {\r
061d5462
ED
3803 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3804 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
3805 ASSERT (NewString != NULL);\r
3806\r
3807 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
3808 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
3809 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
3810 } else {\r
3811 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
3812 }\r
3813\r
3814 FreePool (NewString);\r
3815 }\r
ee31d1be
ED
3816 return Status;\r
3817 }\r
3818 }\r
3819\r
3820 //\r
3821 // Get default value from altcfg string.\r
3822 //\r
3823 if (ConfigAccess != NULL) { \r
3824 Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
3825 if (!EFI_ERROR (Status)) {\r
3826 return Status;\r
3827 }\r
3828 }\r
3829\r
7936fb6a 3830 //\r
3831 // EFI_IFR_DEFAULT has highest priority\r
3832 //\r
3833 if (!IsListEmpty (&Question->DefaultListHead)) {\r
3834 Link = GetFirstNode (&Question->DefaultListHead);\r
3835 while (!IsNull (&Question->DefaultListHead, Link)) {\r
3836 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
3837\r
3838 if (Default->DefaultId == DefaultId) {\r
3839 if (Default->ValueExpression != NULL) {\r
3840 //\r
3841 // Default is provided by an Expression, evaluate it\r
3842 //\r
3843 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
3844 if (EFI_ERROR (Status)) {\r
3845 return Status;\r
3846 }\r
3847\r
901ba0e7
ED
3848 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
3849 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
3850 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
3851 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
3852 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
3853 } else {\r
3854 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
3855 Question->HiiValue.BufferLen = Question->StorageWidth;\r
3856 }\r
3857 FreePool (Default->ValueExpression->Result.Buffer);\r
3858 }\r
3859 HiiValue->Type = Default->ValueExpression->Result.Type;\r
3860 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 3861 } else {\r
3862 //\r
3863 // Default value is embedded in EFI_IFR_DEFAULT\r
3864 //\r
3865 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
3866 }\r
3867\r
086cd2c8
LG
3868 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3869 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
3870 if (StrValue == NULL) {\r
3871 return EFI_NOT_FOUND;\r
3872 }\r
ba944801
ED
3873 if (Question->StorageWidth > StrSize (StrValue)) {\r
3874 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
3875 } else {\r
3876 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
3877 }\r
086cd2c8
LG
3878 }\r
3879\r
7936fb6a 3880 return EFI_SUCCESS;\r
3881 }\r
3882\r
3883 Link = GetNextNode (&Question->DefaultListHead, Link);\r
3884 }\r
3885 }\r
3886\r
3887 //\r
3888 // EFI_ONE_OF_OPTION\r
3889 //\r
3890 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
3891 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3892 //\r
3893 // OneOfOption could only provide Standard and Manufacturing default\r
3894 //\r
3895 Link = GetFirstNode (&Question->OptionListHead);\r
3896 while (!IsNull (&Question->OptionListHead, Link)) {\r
3897 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3898 Link = GetNextNode (&Question->OptionListHead, Link);\r
3899\r
3900 if ((Option->SuppressExpression != NULL) &&\r
3901 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3902 continue;\r
3903 }\r
7936fb6a 3904\r
3905 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
3906 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
3907 ) {\r
3908 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3909\r
3910 return EFI_SUCCESS;\r
3911 }\r
7936fb6a 3912 }\r
3913 }\r
3914 }\r
3915\r
3916 //\r
3917 // EFI_IFR_CHECKBOX - lowest priority\r
3918 //\r
3919 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
3920 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3921 //\r
3922 // Checkbox could only provide Standard and Manufacturing default\r
3923 //\r
3924 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
3925 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
3926 ) {\r
3927 HiiValue->Value.b = TRUE;\r
3928 } else {\r
3929 HiiValue->Value.b = FALSE;\r
3930 }\r
3931\r
3932 return EFI_SUCCESS;\r
3933 }\r
3934 }\r
3935\r
3936 //\r
3937 // For Questions without default\r
3938 //\r
48a9d5f7 3939 Status = EFI_NOT_FOUND;\r
7936fb6a 3940 switch (Question->Operand) {\r
cf4c5a42
LG
3941 case EFI_IFR_NUMERIC_OP:\r
3942 //\r
3943 // Take minimum value as numeric default value\r
3944 //\r
3945 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
3946 HiiValue->Value.u64 = Question->Minimum;\r
48a9d5f7 3947 Status = EFI_SUCCESS;\r
cf4c5a42
LG
3948 }\r
3949 break;\r
3950\r
7936fb6a 3951 case EFI_IFR_ONE_OF_OP:\r
3952 //\r
3953 // Take first oneof option as oneof's default value\r
3954 //\r
d66e6c16 3955 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed 3956 Link = GetFirstNode (&Question->OptionListHead);\r
82612023 3957 while (!IsNull (&Question->OptionListHead, Link)) {\r
0a1147ed 3958 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3959 Link = GetNextNode (&Question->OptionListHead, Link);\r
3960\r
3961 if ((Option->SuppressExpression != NULL) &&\r
3962 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3963 continue;\r
3964 }\r
3965\r
0a1147ed 3966 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 3967 Status = EFI_SUCCESS;\r
82612023 3968 break;\r
0a1147ed 3969 }\r
7936fb6a 3970 }\r
3971 break;\r
3972\r
3973 case EFI_IFR_ORDERED_LIST_OP:\r
3974 //\r
3975 // Take option sequence in IFR as ordered list's default value\r
3976 //\r
3977 Index = 0;\r
3978 Link = GetFirstNode (&Question->OptionListHead);\r
3979 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 3980 Status = EFI_SUCCESS;\r
7936fb6a 3981 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3982 Link = GetNextNode (&Question->OptionListHead, Link);\r
3983\r
3984 if ((Option->SuppressExpression != NULL) &&\r
3985 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3986 continue;\r
3987 }\r
7936fb6a 3988\r
d02847d3 3989 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 3990\r
3991 Index++;\r
3992 if (Index >= Question->MaxContainers) {\r
3993 break;\r
3994 }\r
7936fb6a 3995 }\r
3996 break;\r
3997\r
3998 default:\r
7936fb6a 3999 break;\r
4000 }\r
4001\r
4002 return Status;\r
4003}\r
4004\r
4005\r
4006/**\r
9776099f 4007 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 4008\r
09cdd7d2
ED
4009 GetDefaultValueScope parameter decides which questions will reset \r
4010 to its default value.\r
4011\r
7936fb6a 4012 @param FormSet FormSet data structure.\r
48a9d5f7 4013 @param Form Form data structure.\r
7936fb6a 4014 @param DefaultId The Class of the default.\r
48a9d5f7 4015 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 4016 @param GetDefaultValueScope Get default value scope.\r
3347d410 4017 @param Storage Get default value only for this storage.\r
9776099f
ED
4018 @param RetrieveValueFirst Whether call the retrieve call back to\r
4019 get the initial value before get default\r
4020 value.\r
7936fb6a 4021\r
4022 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 4023 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 4024\r
4025**/\r
4026EFI_STATUS\r
48a9d5f7 4027ExtractDefault (\r
7936fb6a 4028 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
4029 IN FORM_BROWSER_FORM *Form,\r
4030 IN UINT16 DefaultId,\r
3347d410 4031 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 4032 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
94f3aae7 4033 IN BROWSER_STORAGE *Storage OPTIONAL,\r
9776099f 4034 IN BOOLEAN RetrieveValueFirst\r
7936fb6a 4035 )\r
4036{\r
4037 EFI_STATUS Status;\r
4f33c838 4038 LIST_ENTRY *FormLink;\r
48a9d5f7 4039 LIST_ENTRY *Link;\r
7936fb6a 4040 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7 4041 FORM_BROWSER_FORMSET *LocalFormSet;\r
6e74560f 4042 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 4043\r
9776099f
ED
4044 Status = EFI_SUCCESS;\r
4045\r
48a9d5f7
LG
4046 //\r
4047 // Check the supported setting level.\r
4048 //\r
09cdd7d2
ED
4049 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
4050 return EFI_UNSUPPORTED;\r
4051 }\r
4052\r
4053 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
4054 return EFI_UNSUPPORTED;\r
4055 }\r
4056 \r
4057 if (SettingScope == FormLevel) {\r
8d00a0f1 4058 //\r
4f33c838 4059 // Extract Form default\r
8d00a0f1 4060 //\r
48a9d5f7
LG
4061 Link = GetFirstNode (&Form->StatementListHead);\r
4062 while (!IsNull (&Form->StatementListHead, Link)) {\r
4063 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4064 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
4065\r
4066 //\r
4067 // If get default value only for this storage, check the storage first.\r
4068 //\r
09cdd7d2
ED
4069 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
4070 continue;\r
4071 }\r
4072\r
4073 //\r
4074 // If get default value only for no storage question, just skip the question which has storage.\r
4075 //\r
4076 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
4077 continue;\r
4078 }\r
4079\r
4f33c838
ED
4080 //\r
4081 // If Question is disabled, don't reset it to default\r
4082 //\r
31585af4
ED
4083 if (Question->Expression != NULL) {\r
4084 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
4085 continue;\r
4086 }\r
8d00a0f1 4087 }\r
9776099f
ED
4088\r
4089 if (RetrieveValueFirst) {\r
4090 //\r
4091 // Call the Retrieve call back to get the initial question value.\r
4092 //\r
061d5462 4093 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
9776099f
ED
4094 }\r
4095\r
4f33c838 4096 //\r
9776099f 4097 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 4098 //\r
9776099f
ED
4099 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
4100 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
4101 if (EFI_ERROR (Status)) {\r
4102 continue;\r
4103 }\r
4f33c838 4104 }\r
9776099f 4105\r
4f33c838
ED
4106 //\r
4107 // Synchronize Buffer storage's Edit buffer\r
4108 //\r
4109 if ((Question->Storage != NULL) &&\r
4110 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 4111 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
4112 }\r
4113 }\r
4114 } else if (SettingScope == FormSetLevel) {\r
4115 FormLink = GetFirstNode (&FormSet->FormListHead);\r
4116 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
4117 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
9776099f 4118 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
48a9d5f7
LG
4119 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
4120 }\r
4121 } else if (SettingScope == SystemLevel) {\r
4122 //\r
7c6c064c 4123 // Preload all Hii formset.\r
48a9d5f7 4124 //\r
7c6c064c 4125 LoadAllHiiFormset();\r
6e74560f
ED
4126\r
4127 OldFormSet = mSystemLevelFormSet;\r
4128\r
48a9d5f7
LG
4129 //\r
4130 // Set Default Value for each FormSet in the maintain list.\r
4131 //\r
4132 Link = GetFirstNode (&gBrowserFormSetList);\r
4133 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4134 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 4135 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
4136 if (!ValidateFormSet(LocalFormSet)) {\r
4137 continue;\r
4138 }\r
6e74560f
ED
4139\r
4140 mSystemLevelFormSet = LocalFormSet;\r
4141\r
938baa1f 4142 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
7936fb6a 4143 }\r
6e74560f
ED
4144\r
4145 mSystemLevelFormSet = OldFormSet;\r
7936fb6a 4146 }\r
4147\r
4148 return EFI_SUCCESS;\r
4149}\r
4150\r
7c6c064c
ED
4151\r
4152/**\r
4153 Validate whether this question's value has changed.\r
4154\r
4155 @param FormSet FormSet data structure.\r
4156 @param Form Form data structure.\r
4157 @param Question Question to be initialized.\r
4158 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
4159\r
4160 @retval TRUE Question's value has changed.\r
4161 @retval FALSE Question's value has not changed\r
4162\r
4163**/\r
4164BOOLEAN\r
4165IsQuestionValueChanged (\r
4166 IN FORM_BROWSER_FORMSET *FormSet,\r
4167 IN FORM_BROWSER_FORM *Form,\r
4168 IN OUT FORM_BROWSER_STATEMENT *Question,\r
4169 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
4170 )\r
4171{\r
4172 EFI_HII_VALUE BackUpValue;\r
4173 CHAR8 *BackUpBuffer;\r
4d4deaac
ED
4174 EFI_HII_VALUE BackUpValue2;\r
4175 CHAR8 *BackUpBuffer2;\r
7c6c064c
ED
4176 EFI_STATUS Status;\r
4177 BOOLEAN ValueChanged;\r
4178 UINTN BufferWidth;\r
4179\r
4180 //\r
4181 // For quetion without storage, always mark it as data not changed.\r
4182 //\r
4183 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
4184 return FALSE;\r
4185 }\r
4186\r
4187 BackUpBuffer = NULL;\r
4d4deaac 4188 BackUpBuffer2 = NULL;\r
7c6c064c
ED
4189 ValueChanged = FALSE;\r
4190\r
4191 switch (Question->Operand) {\r
4192 case EFI_IFR_ORDERED_LIST_OP:\r
4193 BufferWidth = Question->StorageWidth;\r
4194 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4195 ASSERT (BackUpBuffer != NULL);\r
4196 break;\r
4197\r
4198 case EFI_IFR_STRING_OP:\r
4199 case EFI_IFR_PASSWORD_OP:\r
4200 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4201 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4202 ASSERT (BackUpBuffer != NULL);\r
4203 break;\r
4204\r
4205 default:\r
4206 BufferWidth = 0;\r
4207 break;\r
4208 }\r
4209 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4210\r
4d4deaac
ED
4211 if (GetValueFrom == GetSetValueWithBothBuffer) {\r
4212 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4213 ASSERT_EFI_ERROR(Status);\r
7c6c064c 4214\r
4d4deaac
ED
4215 switch (Question->Operand) {\r
4216 case EFI_IFR_ORDERED_LIST_OP:\r
4217 BufferWidth = Question->StorageWidth;\r
4218 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4219 ASSERT (BackUpBuffer2 != NULL);\r
4220 break;\r
4221\r
4222 case EFI_IFR_STRING_OP:\r
4223 case EFI_IFR_PASSWORD_OP:\r
4224 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4225 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4226 ASSERT (BackUpBuffer2 != NULL);\r
4227 break;\r
4228\r
4229 default:\r
4230 BufferWidth = 0;\r
4231 break;\r
4232 }\r
4233 CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4234\r
4235 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
4236 ASSERT_EFI_ERROR(Status);\r
4237\r
4238 if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4239 CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
4240 ValueChanged = TRUE;\r
4241 }\r
4242 } else {\r
4243 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
4244 ASSERT_EFI_ERROR(Status);\r
4245\r
4246 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4247 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
4248 ValueChanged = TRUE;\r
4249 }\r
7c6c064c
ED
4250 }\r
4251\r
4252 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
7c6c064c 4253 if (BackUpBuffer != NULL) {\r
e77d2f9d 4254 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
7c6c064c
ED
4255 FreePool (BackUpBuffer);\r
4256 }\r
4257\r
4d4deaac
ED
4258 if (BackUpBuffer2 != NULL) {\r
4259 FreePool (BackUpBuffer2);\r
4260 }\r
4261\r
892eccc8
ED
4262 Question->ValueChanged = ValueChanged;\r
4263\r
7c6c064c
ED
4264 return ValueChanged;\r
4265}\r
4266\r
7936fb6a 4267/**\r
4268 Initialize Question's Edit copy from Storage.\r
4269\r
eccfeab1
LG
4270 @param Selection Selection contains the information about \r
4271 the Selection, form and formset to be displayed.\r
4272 Selection action may be updated in retrieve callback.\r
7d1b202d 4273 If Selection is NULL, only initialize Question value.\r
7936fb6a 4274 @param FormSet FormSet data structure.\r
4275 @param Form Form data structure.\r
4276\r
4277 @retval EFI_SUCCESS The function completed successfully.\r
4278\r
4279**/\r
4280EFI_STATUS\r
4281LoadFormConfig (\r
eccfeab1
LG
4282 IN OUT UI_MENU_SELECTION *Selection,\r
4283 IN FORM_BROWSER_FORMSET *FormSet,\r
4284 IN FORM_BROWSER_FORM *Form\r
7936fb6a 4285 )\r
4286{\r
eccfeab1
LG
4287 EFI_STATUS Status;\r
4288 LIST_ENTRY *Link;\r
4289 FORM_BROWSER_STATEMENT *Question;\r
eccfeab1 4290 \r
7936fb6a 4291 Link = GetFirstNode (&Form->StatementListHead);\r
4292 while (!IsNull (&Form->StatementListHead, Link)) {\r
4293 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4294\r
4295 //\r
4296 // Initialize local copy of Value for each Question\r
4297 //\r
7c6c064c
ED
4298 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
4299 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
4300 } else {\r
4301 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4302 }\r
7936fb6a 4303 if (EFI_ERROR (Status)) {\r
4304 return Status;\r
4305 }\r
e2100bfa
ED
4306\r
4307 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
4308 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
4309 }\r
4310\r
7936fb6a 4311 Link = GetNextNode (&Form->StatementListHead, Link);\r
4312 }\r
4313\r
4314 return EFI_SUCCESS;\r
4315}\r
4316\r
d66e6c16 4317/**\r
4318 Initialize Question's Edit copy from Storage for the whole Formset.\r
4319\r
eccfeab1
LG
4320 @param Selection Selection contains the information about \r
4321 the Selection, form and formset to be displayed.\r
4322 Selection action may be updated in retrieve callback.\r
7d1b202d 4323 If Selection is NULL, only initialize Question value.\r
d66e6c16 4324 @param FormSet FormSet data structure.\r
4325\r
4326 @retval EFI_SUCCESS The function completed successfully.\r
4327\r
4328**/\r
4329EFI_STATUS\r
4330LoadFormSetConfig (\r
eccfeab1
LG
4331 IN OUT UI_MENU_SELECTION *Selection,\r
4332 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 4333 )\r
4334{\r
eccfeab1
LG
4335 EFI_STATUS Status;\r
4336 LIST_ENTRY *Link;\r
4337 FORM_BROWSER_FORM *Form;\r
d66e6c16 4338\r
4339 Link = GetFirstNode (&FormSet->FormListHead);\r
4340 while (!IsNull (&FormSet->FormListHead, Link)) {\r
4341 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4342\r
4343 //\r
4344 // Initialize local copy of Value for each Form\r
4345 //\r
eccfeab1 4346 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 4347 if (EFI_ERROR (Status)) {\r
4348 return Status;\r
4349 }\r
4350\r
4351 Link = GetNextNode (&FormSet->FormListHead, Link);\r
4352 }\r
4353\r
7c6c064c
ED
4354 //\r
4355 // Finished question initialization.\r
4356 // \r
4357 FormSet->QuestionInited = TRUE;\r
4358\r
d66e6c16 4359 return EFI_SUCCESS;\r
4360}\r
4361\r
0a6f8af5
ED
4362/**\r
4363 Remove the Request element from the Config Request.\r
4364\r
4365 @param Storage Pointer to the browser storage.\r
4366 @param RequestElement The pointer to the Request element.\r
4367\r
4368**/\r
4369VOID\r
4370RemoveElement (\r
4371 IN OUT BROWSER_STORAGE *Storage,\r
4372 IN CHAR16 *RequestElement\r
4373 )\r
4374{\r
4375 CHAR16 *NewStr;\r
4376 CHAR16 *DestStr;\r
4377\r
4378 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
4379\r
4380 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
4381\r
4382 if (NewStr == NULL) {\r
4383 return;\r
4384 }\r
4385\r
4386 //\r
4387 // Remove this element from this ConfigRequest.\r
4388 //\r
4389 DestStr = NewStr;\r
4390 NewStr += StrLen (RequestElement);\r
4391 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
4392 \r
4393 Storage->SpareStrLen += StrLen (RequestElement); \r
4394}\r
4395\r
4396/**\r
4397 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
4398\r
4399 @param Storage Pointer to the browser storage.\r
4400 @param ConfigRequest The pointer to the Request element.\r
4401\r
4402**/\r
4403VOID\r
4404RemoveConfigRequest (\r
4405 BROWSER_STORAGE *Storage,\r
4406 CHAR16 *ConfigRequest\r
4407 )\r
4408{\r
4409 CHAR16 *RequestElement;\r
4410 CHAR16 *NextRequestElement;\r
4411 CHAR16 *SearchKey;\r
4412\r
7c6c064c
ED
4413 //\r
4414 // No request element in it, just return.\r
4415 //\r
4416 if (ConfigRequest == NULL) {\r
4417 return;\r
4418 }\r
4419\r
0a6f8af5
ED
4420 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4421 //\r
4422 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4423 //\r
4424 SearchKey = L"&";\r
4425 } else {\r
4426 //\r
4427 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4428 //\r
4429 SearchKey = L"&OFFSET";\r
4430 }\r
4431\r
4432 //\r
4433 // Find SearchKey storage\r
4434 //\r
4435 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4436 RequestElement = StrStr (ConfigRequest, L"PATH");\r
4437 ASSERT (RequestElement != NULL);\r
4438 RequestElement = StrStr (RequestElement, SearchKey); \r
4439 } else {\r
4440 RequestElement = StrStr (ConfigRequest, SearchKey);\r
4441 }\r
4442\r
4443 while (RequestElement != NULL) {\r
4444 //\r
4445 // +1 to avoid find header itself.\r
4446 //\r
4447 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4448\r
4449 //\r
4450 // The last Request element in configRequest string.\r
4451 //\r
4452 if (NextRequestElement != NULL) {\r
4453 //\r
4454 // Replace "&" with '\0'.\r
4455 //\r
4456 *NextRequestElement = L'\0';\r
4457 }\r
4458\r
4459 RemoveElement (Storage, RequestElement);\r
4460\r
4461 if (NextRequestElement != NULL) {\r
4462 //\r
4463 // Restore '&' with '\0' for later used.\r
4464 //\r
4465 *NextRequestElement = L'&';\r
4466 }\r
4467\r
4468 RequestElement = NextRequestElement;\r
4469 }\r
4470\r
4471 //\r
4472 // If no request element remain, just remove the ConfigRequest string.\r
4473 //\r
4474 if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
4475 FreePool (Storage->ConfigRequest);\r
4476 Storage->ConfigRequest = NULL;\r
4477 Storage->SpareStrLen = 0;\r
4478 }\r
4479}\r
4480\r
4481/**\r
4482 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
4483\r
4484 @param FormSet Pointer of the FormSet\r
4485\r
4486**/\r
4487VOID\r
4488CleanBrowserStorage (\r
4489 IN OUT FORM_BROWSER_FORMSET *FormSet\r
4490 )\r
4491{\r
4492 LIST_ENTRY *Link;\r
4493 FORMSET_STORAGE *Storage;\r
4494\r
4495 Link = GetFirstNode (&FormSet->StorageListHead);\r
4496 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4497 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
4498 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4499\r
fae73624
ED
4500 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
4501 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
4502 continue;\r
4503 }\r
0a6f8af5 4504\r
9d34cac8 4505 RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);\r
fae73624
ED
4506 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
4507 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4508 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
4509 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5dc6ab16 4510 Storage->BrowserStorage->ConfigRequest = NULL;\r
fae73624
ED
4511 }\r
4512 Storage->BrowserStorage->Initialized = FALSE;\r
0a6f8af5 4513 }\r
0a6f8af5
ED
4514 }\r
4515}\r
4516\r
efffd9c1
ED
4517/**\r
4518 Check whether current element in the ConfigReqeust string.\r
4519\r
4520 @param BrowserStorage Storage which includes ConfigReqeust.\r
4521 @param RequestElement New element need to check.\r
4522\r
4523 @retval TRUE The Element is in the ConfigReqeust string.\r
4524 @retval FALSE The Element not in the configReqeust String.\r
4525\r
4526**/\r
4527BOOLEAN \r
4528ElementValidation (\r
4529 BROWSER_STORAGE *BrowserStorage,\r
4530 CHAR16 *RequestElement\r
4531 )\r
4532{\r
4533 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
4534}\r
4535\r
4536/**\r
4537 Append the Request element to the Config Request.\r
4538\r
4539 @param ConfigRequest Current ConfigRequest info.\r
4540 @param SpareStrLen Current remain free buffer for config reqeust.\r
4541 @param RequestElement New Request element.\r
4542\r
4543**/\r
4544VOID\r
4545AppendConfigRequest (\r
4546 IN OUT CHAR16 **ConfigRequest,\r
4547 IN OUT UINTN *SpareStrLen,\r
4548 IN CHAR16 *RequestElement\r
4549 )\r
4550{\r
4551 CHAR16 *NewStr;\r
4552 UINTN StringSize;\r
4553 UINTN StrLength;\r
4554\r
0a6f8af5 4555 StrLength = StrLen (RequestElement);\r
efffd9c1
ED
4556\r
4557 //\r
4558 // Append <RequestElement> to <ConfigRequest>\r
4559 //\r
4560 if (StrLength > *SpareStrLen) {\r
4561 //\r
4562 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
4563 //\r
4564 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
4565 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
4566 ASSERT (NewStr != NULL);\r
4567\r
4568 if (*ConfigRequest != NULL) {\r
4569 CopyMem (NewStr, *ConfigRequest, StringSize);\r
4570 FreePool (*ConfigRequest);\r
4571 }\r
4572 *ConfigRequest = NewStr;\r
4573 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
4574 }\r
4575\r
4576 StrCat (*ConfigRequest, RequestElement);\r
4577 *SpareStrLen -= StrLength;\r
4578}\r
4579\r
4580/**\r
4581 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
4582\r
4583 @param Storage Form set Storage.\r
9d34cac8
ED
4584 @param Request The input request string.\r
4585 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
efffd9c1
ED
4586\r
4587 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
4588 @retval FALSE All elements covered by current used elements.\r
4589\r
4590**/\r
4591BOOLEAN \r
4592ConfigRequestAdjust (\r
9d34cac8
ED
4593 IN BROWSER_STORAGE *Storage,\r
4594 IN CHAR16 *Request,\r
4595 IN BOOLEAN RespString\r
efffd9c1
ED
4596 )\r
4597{\r
4598 CHAR16 *RequestElement;\r
4599 CHAR16 *NextRequestElement;\r
9d34cac8 4600 CHAR16 *NextElementBakup;\r
efffd9c1
ED
4601 UINTN SpareBufLen;\r
4602 CHAR16 *SearchKey;\r
9d34cac8 4603 CHAR16 *ValueKey;\r
efffd9c1 4604 BOOLEAN RetVal;\r
9d34cac8 4605 CHAR16 *ConfigRequest;\r
efffd9c1
ED
4606\r
4607 SpareBufLen = 0;\r
efffd9c1 4608 RetVal = FALSE;\r
9d34cac8
ED
4609 NextElementBakup = NULL;\r
4610 ValueKey = NULL;\r
efffd9c1 4611\r
9d34cac8
ED
4612 if (Request != NULL) {\r
4613 ConfigRequest = Request;\r
4614 } else {\r
4615 ConfigRequest = Storage->ConfigRequest;\r
4616 }\r
4617\r
4618 if (Storage->ConfigRequest == NULL) {\r
4619 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
efffd9c1
ED
4620 return TRUE;\r
4621 }\r
4622\r
9d34cac8 4623 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
efffd9c1
ED
4624 //\r
4625 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4626 //\r
4627 SearchKey = L"&";\r
4628 } else {\r
4629 //\r
4630 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4631 //\r
4632 SearchKey = L"&OFFSET";\r
9d34cac8 4633 ValueKey = L"&VALUE";\r
efffd9c1
ED
4634 }\r
4635\r
efffd9c1
ED
4636 //\r
4637 // Find SearchKey storage\r
4638 //\r
9d34cac8
ED
4639 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4640 RequestElement = StrStr (ConfigRequest, L"PATH");\r
efffd9c1
ED
4641 ASSERT (RequestElement != NULL);\r
4642 RequestElement = StrStr (RequestElement, SearchKey); \r
4643 } else {\r
9d34cac8 4644 RequestElement = StrStr (ConfigRequest, SearchKey);\r
efffd9c1
ED
4645 }\r
4646\r
4647 while (RequestElement != NULL) {\r
9d34cac8 4648\r
efffd9c1
ED
4649 //\r
4650 // +1 to avoid find header itself.\r
4651 //\r
4652 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4653\r
4654 //\r
4655 // The last Request element in configRequest string.\r
4656 //\r
4657 if (NextRequestElement != NULL) {\r
9d34cac8
ED
4658 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4659 NextElementBakup = NextRequestElement;\r
4660 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 4661 ASSERT (NextRequestElement != NULL);\r
9d34cac8 4662 }\r
efffd9c1
ED
4663 //\r
4664 // Replace "&" with '\0'.\r
4665 //\r
4666 *NextRequestElement = L'\0';\r
9d34cac8
ED
4667 } else {\r
4668 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4669 NextElementBakup = NextRequestElement;\r
4670 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 4671 ASSERT (NextRequestElement != NULL);\r
9d34cac8
ED
4672 //\r
4673 // Replace "&" with '\0'.\r
4674 //\r
4675 *NextRequestElement = L'\0';\r
4676 }\r
efffd9c1
ED
4677 }\r
4678 \r
9d34cac8 4679 if (!ElementValidation (Storage, RequestElement)) {\r
efffd9c1
ED
4680 //\r
4681 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
4682 //\r
9d34cac8 4683 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
efffd9c1
ED
4684 RetVal = TRUE;\r
4685 }\r
4686\r
4687 if (NextRequestElement != NULL) {\r
4688 //\r
4689 // Restore '&' with '\0' for later used.\r
4690 //\r
4691 *NextRequestElement = L'&';\r
4692 }\r
4693\r
9d34cac8
ED
4694 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4695 RequestElement = NextElementBakup;\r
4696 } else {\r
4697 RequestElement = NextRequestElement;\r
7c6c064c 4698 }\r
efffd9c1
ED
4699 }\r
4700\r
4701 return RetVal;\r
4702}\r
4703\r
7c6c064c
ED
4704/**\r
4705\r
4706 Base on ConfigRequest info to get default value for current formset. \r
4707\r
4708 ConfigRequest info include the info about which questions in current formset need to \r
4709 get default value. This function only get these questions default value.\r
4710 \r
4711 @param FormSet FormSet data structure.\r
4712 @param Storage Storage need to update value.\r
4713 @param ConfigRequest The config request string.\r
4714\r
4715**/\r
4716VOID\r
4717GetDefaultForFormset (\r
4718 IN FORM_BROWSER_FORMSET *FormSet,\r
4719 IN BROWSER_STORAGE *Storage,\r
4720 IN CHAR16 *ConfigRequest\r
4721 )\r
4722{\r
4723 UINT8 *BackUpBuf;\r
4724 UINTN BufferSize;\r
4725 LIST_ENTRY BackUpList;\r
4726 NAME_VALUE_NODE *Node;\r
4727 LIST_ENTRY *Link;\r
4728 LIST_ENTRY *NodeLink;\r
4729 NAME_VALUE_NODE *TmpNode;\r
4730 EFI_STATUS Status;\r
4731 EFI_STRING Progress;\r
4732 EFI_STRING Result;\r
4733\r
4734 BackUpBuf = NULL;\r
4735 InitializeListHead(&BackUpList);\r
4736\r
4737 //\r
4738 // Back update the edit buffer.\r
4739 // \r
4740 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
4741 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4742 BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer);\r
4743 ASSERT (BackUpBuf != NULL);\r
4744 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4745 Link = GetFirstNode (&Storage->NameValueListHead);\r
4746 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
4747 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4748 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
4749\r
4750 //\r
4751 // Only back Node belong to this formset.\r
4752 //\r
4753 if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) {\r
4754 continue;\r
4755 }\r
4756\r
4757 TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node);\r
523f48e7 4758 ASSERT (TmpNode != NULL);\r
7c6c064c 4759 TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name);\r
523f48e7 4760 ASSERT (TmpNode->Name != NULL);\r
7c6c064c 4761 TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
523f48e7 4762 ASSERT (TmpNode->EditValue != NULL);\r
7c6c064c
ED
4763\r
4764 InsertTailList(&BackUpList, &TmpNode->Link);\r
4765 }\r
4766 }\r
4767\r
4768 //\r
4769 // Get default value.\r
4770 //\r
4771 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
4772\r
4773 //\r
4774 // Update the question value based on the input ConfigRequest.\r
4775 //\r
4776 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
4777 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4778 ASSERT (BackUpBuf != NULL);\r
4779 BufferSize = Storage->Size;\r
4780 Status = mHiiConfigRouting->BlockToConfig(\r
4781 mHiiConfigRouting,\r
4782 ConfigRequest,\r
4783 Storage->EditBuffer,\r
4784 BufferSize,\r
4785 &Result,\r
4786 &Progress\r
4787 );\r
4788 ASSERT_EFI_ERROR (Status);\r
4789 \r
4790 Status = mHiiConfigRouting->ConfigToBlock (\r
4791 mHiiConfigRouting,\r
4792 Result,\r
4793 BackUpBuf,\r
4794 &BufferSize,\r
4795 &Progress\r
4796 );\r
4797 ASSERT_EFI_ERROR (Status);\r
4798\r
4799 if (Result != NULL) {\r
4800 FreePool (Result);\r
4801 }\r
4802 \r
4803 CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size);\r
4804 FreePool (BackUpBuf);\r
4805 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4806 //\r
4807 // Update question value, only element in ConfigReqeust will be update.\r
4808 //\r
4809 Link = GetFirstNode (&BackUpList);\r
4810 while (!IsNull (&BackUpList, Link)) {\r
4811 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4812 Link = GetNextNode (&BackUpList, Link);\r
4813\r
4814 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
4815 continue;\r
4816 }\r
4817\r
4818 NodeLink = GetFirstNode (&Storage->NameValueListHead);\r
4819 while (!IsNull (&Storage->NameValueListHead, NodeLink)) {\r
4820 TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink);\r
4821 NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink);\r
4822 \r
4823 if (StrCmp (Node->Name, TmpNode->Name) != 0) {\r
4824 continue;\r
4825 }\r
4826\r
4827 FreePool (TmpNode->EditValue);\r
4828 TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
4829\r
4830 RemoveEntryList (&Node->Link);\r
4831 FreePool (Node->EditValue);\r
4832 FreePool (Node->Name);\r
4833 FreePool (Node);\r
4834 }\r
4835 }\r
4836\r
4837 //\r
4838 // Restore the Name/Value node.\r
4839 // \r
4840 Link = GetFirstNode (&BackUpList);\r
4841 while (!IsNull (&BackUpList, Link)) {\r
4842 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
4843 Link = GetNextNode (&BackUpList, Link);\r
4844 \r
4845 //\r
4846 // Free this node.\r
4847 //\r
4848 RemoveEntryList (&Node->Link);\r
4849 FreePool (Node->EditValue);\r
4850 FreePool (Node->Name);\r
4851 FreePool (Node);\r
4852 }\r
4853 }\r
4854}\r
4855\r
7936fb6a 4856/**\r
4857 Fill storage's edit copy with settings requested from Configuration Driver.\r
4858\r
4859 @param FormSet FormSet data structure.\r
4860 @param Storage Buffer Storage.\r
4861\r
7936fb6a 4862**/\r
7c6c064c 4863VOID\r
7936fb6a 4864LoadStorage (\r
4865 IN FORM_BROWSER_FORMSET *FormSet,\r
4866 IN FORMSET_STORAGE *Storage\r
4867 )\r
4868{\r
4869 EFI_STATUS Status;\r
4870 EFI_STRING Progress;\r
4871 EFI_STRING Result;\r
4872 CHAR16 *StrPtr;\r
98c4caa1
ED
4873 EFI_STRING ConfigRequest;\r
4874 UINTN StrLen;\r
4875\r
4876 ConfigRequest = NULL;\r
7936fb6a 4877\r
7c6c064c
ED
4878 switch (Storage->BrowserStorage->Type) {\r
4879 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
4880 return;\r
4881\r
4882 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
6e74560f 4883 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
9d34cac8 4884 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
7c6c064c
ED
4885 return;\r
4886 }\r
7c6c064c 4887 break;\r
cce6230f 4888\r
7c6c064c
ED
4889 case EFI_HII_VARSTORE_BUFFER:\r
4890 case EFI_HII_VARSTORE_NAME_VALUE:\r
4891 //\r
27c304f4 4892 // Skip if there is no RequestElement.\r
7c6c064c 4893 //\r
27c304f4 4894 if (Storage->ElementCount == 0) {\r
7c6c064c
ED
4895 return;\r
4896 }\r
27c304f4
ED
4897\r
4898 //\r
4899 // Just update the ConfigRequest, if storage already initialized. \r
4900 //\r
4901 if (Storage->BrowserStorage->Initialized) {\r
9d34cac8 4902 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
27c304f4
ED
4903 return;\r
4904 }\r
4905\r
fae73624 4906 Storage->BrowserStorage->Initialized = TRUE;\r
7c6c064c 4907 break;\r
7936fb6a 4908\r
7c6c064c 4909 default:\r
7248790e 4910 return;\r
7936fb6a 4911 }\r
7248790e 4912\r
27c304f4
ED
4913 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
4914 //\r
4915 // Create the config request string to get all fields for this storage.\r
4916 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
4917 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
4918 //\r
4919 StrLen = StrSize (Storage->BrowserStorage->ConfigHdr) + 20 * sizeof (CHAR16);\r
4920 ConfigRequest = AllocateZeroPool (StrLen);\r
4921 ASSERT (ConfigRequest != NULL);\r
4922 UnicodeSPrint (\r
4923 ConfigRequest, \r
4924 StrLen, \r
4925 L"%s&OFFSET=0&WIDTH=%04x", \r
4926 Storage->BrowserStorage->ConfigHdr,\r
4927 Storage->BrowserStorage->Size);\r
4928 } else {\r
4929 ConfigRequest = Storage->ConfigRequest;\r
4930 }\r
4931\r
7248790e
ED
4932 //\r
4933 // Request current settings from Configuration Driver\r
4934 //\r
4935 Status = mHiiConfigRouting->ExtractConfig (\r
4936 mHiiConfigRouting,\r
98c4caa1 4937 ConfigRequest,\r
7248790e
ED
4938 &Progress,\r
4939 &Result\r
4940 );\r
4941\r
4942 //\r
4943 // If get value fail, extract default from IFR binary\r
4944 //\r
4945 if (EFI_ERROR (Status)) {\r
4946 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);\r
4947 } else {\r
4948 //\r
4949 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
4950 //\r
4951 StrPtr = StrStr (Result, L"&GUID=");\r
4952 if (StrPtr != NULL) {\r
4953 *StrPtr = L'\0';\r
4954 }\r
4955 \r
4956 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
4957 FreePool (Result);\r
4958 }\r
4959\r
4960 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
4961\r
4962 //\r
4963 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
4964 //\r
4d4deaac 4965 SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
98c4caa1 4966\r
27c304f4 4967 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
98c4caa1
ED
4968 if (ConfigRequest != NULL) {\r
4969 FreePool (ConfigRequest);\r
4970 }\r
4971 }\r
7936fb6a 4972}\r
4973\r
892eccc8
ED
4974/**\r
4975 Get Value changed status from old question.\r
4976\r
4977 @param NewFormSet FormSet data structure.\r
4978 @param OldQuestion Old question which has value changed.\r
4979\r
4980**/\r
4981VOID\r
4982SyncStatusForQuestion (\r
4983 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
4984 IN FORM_BROWSER_STATEMENT *OldQuestion\r
4985 )\r
4986{\r
4987 LIST_ENTRY *Link;\r
4988 LIST_ENTRY *QuestionLink;\r
4989 FORM_BROWSER_FORM *Form;\r
4990 FORM_BROWSER_STATEMENT *Question;\r
4991\r
4992 //\r
4993 // For each form in one formset.\r
4994 //\r
4995 Link = GetFirstNode (&NewFormSet->FormListHead);\r
4996 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
4997 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4998 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
4999\r
5000 //\r
5001 // for each question in one form.\r
5002 //\r
5003 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5004 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5005 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5006 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5007\r
5008 if (Question->QuestionId == OldQuestion->QuestionId) {\r
5009 Question->ValueChanged = TRUE;\r
5010 return;\r
5011 }\r
5012 }\r
5013 }\r
5014}\r
5015\r
5016/**\r
5017 Get Value changed status from old formset.\r
5018\r
5019 @param NewFormSet FormSet data structure.\r
5020 @param OldFormSet FormSet data structure.\r
5021\r
5022**/\r
5023VOID\r
5024SyncStatusForFormSet (\r
5025 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5026 IN FORM_BROWSER_FORMSET *OldFormSet\r
5027 )\r
5028{\r
5029 LIST_ENTRY *Link;\r
5030 LIST_ENTRY *QuestionLink;\r
5031 FORM_BROWSER_FORM *Form;\r
5032 FORM_BROWSER_STATEMENT *Question;\r
5033\r
5034 //\r
5035 // For each form in one formset.\r
5036 //\r
5037 Link = GetFirstNode (&OldFormSet->FormListHead);\r
5038 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
5039 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5040 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
5041\r
5042 //\r
5043 // for each question in one form.\r
5044 //\r
5045 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5046 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5047 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5048 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5049\r
5050 if (!Question->ValueChanged) {\r
5051 continue;\r
5052 }\r
5053\r
5054 //\r
5055 // Find the same question in new formset and update the value changed flag.\r
5056 //\r
5057 SyncStatusForQuestion (NewFormSet, Question);\r
5058 }\r
5059 }\r
5060}\r
5061\r
7936fb6a 5062/**\r
5063 Get current setting of Questions.\r
5064\r
5065 @param FormSet FormSet data structure.\r
5066\r
7936fb6a 5067**/\r
7c6c064c 5068VOID\r
7936fb6a 5069InitializeCurrentSetting (\r
5070 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5071 )\r
5072{\r
5073 LIST_ENTRY *Link;\r
5074 FORMSET_STORAGE *Storage;\r
7c6c064c 5075 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 5076\r
6e74560f
ED
5077 //\r
5078 // Try to find pre FormSet in the maintain backup list.\r
5079 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
5080 //\r
5081 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
5082 if (OldFormSet != NULL) {\r
892eccc8 5083 SyncStatusForFormSet (FormSet, OldFormSet);\r
6e74560f
ED
5084 RemoveEntryList (&OldFormSet->Link);\r
5085 DestroyFormSet (OldFormSet);\r
5086 }\r
5087 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
5088\r
1deb5cab
ED
5089 //\r
5090 // Extract default from IFR binary for no storage questions.\r
5091 // \r
5092 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE);\r
5093\r
7936fb6a 5094 //\r
5095 // Request current settings from Configuration Driver\r
5096 //\r
5097 Link = GetFirstNode (&FormSet->StorageListHead);\r
5098 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5099 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5100\r
7c6c064c 5101 LoadStorage (FormSet, Storage);\r
7936fb6a 5102\r
7936fb6a 5103 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5104 }\r
7936fb6a 5105}\r
5106\r
5107\r
5108/**\r
5109 Fetch the Ifr binary data of a FormSet.\r
5110\r
5111 @param Handle PackageList Handle\r
f5006bd9 5112 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5113 specified (NULL or zero GUID), take the first\r
5114 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5115 found in package list.\r
5116 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5117 @param BinaryLength The length of the FormSet IFR binary.\r
5118 @param BinaryData The buffer designed to receive the FormSet.\r
5119\r
5120 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
5121 BufferLength was updated.\r
5122 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
5123 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
5124 be found with the requested FormId.\r
5125\r
5126**/\r
5127EFI_STATUS\r
5128GetIfrBinaryData (\r
5129 IN EFI_HII_HANDLE Handle,\r
5130 IN OUT EFI_GUID *FormSetGuid,\r
5131 OUT UINTN *BinaryLength,\r
5132 OUT UINT8 **BinaryData\r
5133 )\r
5134{\r
5135 EFI_STATUS Status;\r
5136 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
5137 UINTN BufferSize;\r
5138 UINT8 *Package;\r
5139 UINT8 *OpCodeData;\r
5140 UINT32 Offset;\r
5141 UINT32 Offset2;\r
7936fb6a 5142 UINT32 PackageListLength;\r
5143 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
5144 UINT8 Index;\r
5145 UINT8 NumberOfClassGuid;\r
f5006bd9 5146 BOOLEAN ClassGuidMatch;\r
0a1147ed 5147 EFI_GUID *ClassGuid;\r
f5006bd9 5148 EFI_GUID *ComparingGuid;\r
7936fb6a 5149\r
5150 OpCodeData = NULL;\r
5151 Package = NULL;\r
0c66bc76 5152 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 5153\r
5154 //\r
f5006bd9 5155 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 5156 //\r
48a9d5f7
LG
5157 if (FormSetGuid == NULL) {\r
5158 ComparingGuid = &gZeroGuid;\r
7936fb6a 5159 } else {\r
f5006bd9 5160 ComparingGuid = FormSetGuid;\r
7936fb6a 5161 }\r
5162\r
5163 //\r
5164 // Get HII PackageList\r
5165 //\r
5166 BufferSize = 0;\r
5167 HiiPackageList = NULL;\r
5168 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5169 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5170 HiiPackageList = AllocatePool (BufferSize);\r
5171 ASSERT (HiiPackageList != NULL);\r
5172\r
5173 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5174 }\r
5175 if (EFI_ERROR (Status)) {\r
5176 return Status;\r
5177 }\r
db0bd81c 5178 ASSERT (HiiPackageList != NULL);\r
d66e6c16 5179\r
7936fb6a 5180 //\r
5181 // Get Form package from this HII package List\r
5182 //\r
5183 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
5184 Offset2 = 0;\r
5185 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
5186\r
f5006bd9 5187 ClassGuidMatch = FALSE;\r
7936fb6a 5188 while (Offset < PackageListLength) {\r
5189 Package = ((UINT8 *) HiiPackageList) + Offset;\r
5190 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
5191\r
8d00a0f1 5192 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 5193 //\r
5194 // Search FormSet in this Form Package\r
5195 //\r
5196 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
5197 while (Offset2 < PackageHeader.Length) {\r
5198 OpCodeData = Package + Offset2;\r
5199\r
5200 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
5201 //\r
f5006bd9 5202 // Try to compare against formset GUID\r
7936fb6a 5203 //\r
48a9d5f7
LG
5204 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
5205 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 5206 break;\r
7936fb6a 5207 }\r
5208\r
d228526f
LG
5209 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
5210 //\r
5211 // Try to compare against formset class GUID\r
5212 //\r
5213 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
5214 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
5215 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
5216 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
5217 ClassGuidMatch = TRUE;\r
5218 break;\r
5219 }\r
5220 }\r
5221 if (ClassGuidMatch) {\r
f5006bd9 5222 break;\r
5223 }\r
d228526f
LG
5224 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
5225 ClassGuidMatch = TRUE;\r
7936fb6a 5226 break;\r
5227 }\r
5228 }\r
5229\r
5230 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
5231 }\r
5232\r
5233 if (Offset2 < PackageHeader.Length) {\r
5234 //\r
5235 // Target formset found\r
5236 //\r
5237 break;\r
5238 }\r
5239 }\r
5240\r
5241 Offset += PackageHeader.Length;\r
5242 }\r
5243\r
5244 if (Offset >= PackageListLength) {\r
5245 //\r
5246 // Form package not found in this Package List\r
5247 //\r
f4113e1f 5248 FreePool (HiiPackageList);\r
7936fb6a 5249 return EFI_NOT_FOUND;\r
5250 }\r
5251\r
48a9d5f7 5252 if (FormSetGuid != NULL) {\r
7936fb6a 5253 //\r
f5006bd9 5254 // Return the FormSet GUID\r
7936fb6a 5255 //\r
5256 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
5257 }\r
5258\r
5259 //\r
5260 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
5261 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
5262 // of the Form Package.\r
5263 //\r
5264 *BinaryLength = PackageHeader.Length - Offset2;\r
5265 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
5266\r
f4113e1f 5267 FreePool (HiiPackageList);\r
7936fb6a 5268\r
5269 if (*BinaryData == NULL) {\r
5270 return EFI_OUT_OF_RESOURCES;\r
5271 }\r
5272\r
5273 return EFI_SUCCESS;\r
5274}\r
5275\r
5276\r
5277/**\r
5278 Initialize the internal data structure of a FormSet.\r
5279\r
5280 @param Handle PackageList Handle\r
f5006bd9 5281 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5282 specified (NULL or zero GUID), take the first\r
5283 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5284 found in package list.\r
5285 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5286 @param FormSet FormSet data structure.\r
5287\r
5288 @retval EFI_SUCCESS The function completed successfully.\r
5289 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
5290\r
5291**/\r
5292EFI_STATUS\r
5293InitializeFormSet (\r
5294 IN EFI_HII_HANDLE Handle,\r
5295 IN OUT EFI_GUID *FormSetGuid,\r
7c6c064c 5296 OUT FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 5297 )\r
5298{\r
5299 EFI_STATUS Status;\r
5300 EFI_HANDLE DriverHandle;\r
7936fb6a 5301\r
5302 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
5303 if (EFI_ERROR (Status)) {\r
5304 return Status;\r
5305 }\r
5306\r
48a9d5f7 5307 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 5308 FormSet->HiiHandle = Handle;\r
5309 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
7c6c064c 5310 FormSet->QuestionInited = FALSE;\r
7936fb6a 5311\r
5312 //\r
5313 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
5314 //\r
5315 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
5316 if (EFI_ERROR (Status)) {\r
5317 return Status;\r
5318 }\r
5319 FormSet->DriverHandle = DriverHandle;\r
5320 Status = gBS->HandleProtocol (\r
5321 DriverHandle,\r
5322 &gEfiHiiConfigAccessProtocolGuid,\r
5323 (VOID **) &FormSet->ConfigAccess\r
5324 );\r
5325 if (EFI_ERROR (Status)) {\r
5326 //\r
5327 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
5328 // list, then there will be no configuration action required\r
5329 //\r
5330 FormSet->ConfigAccess = NULL;\r
5331 }\r
5332\r
5333 //\r
5334 // Parse the IFR binary OpCodes\r
5335 //\r
5336 Status = ParseOpCodes (FormSet);\r
25361615 5337\r
7c6c064c 5338 return Status;\r
7936fb6a 5339}\r
ce6d12cc 5340\r
5341\r
5342/**\r
5343 Save globals used by previous call to SendForm(). SendForm() may be called from \r
5344 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
5345 So, save globals of previous call to SendForm() and restore them upon exit.\r
5346\r
5347**/\r
5348VOID\r
5349SaveBrowserContext (\r
5350 VOID\r
5351 )\r
5352{\r
5353 BROWSER_CONTEXT *Context;\r
7c6c064c 5354 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 5355\r
5356 gBrowserContextCount++;\r
5357 if (gBrowserContextCount == 1) {\r
5358 //\r
5359 // This is not reentry of SendForm(), no context to save\r
5360 //\r
5361 return;\r
5362 }\r
5363\r
5364 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
5365 ASSERT (Context != NULL);\r
5366\r
5367 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
5368\r
5369 //\r
5370 // Save FormBrowser context\r
5371 //\r
5a9f73bf 5372 Context->Selection = gCurrentSelection;\r
ce6d12cc 5373 Context->ResetRequired = gResetRequired;\r
7c6c064c
ED
5374 Context->ExitRequired = gExitRequired;\r
5375 Context->HiiHandle = mCurrentHiiHandle;\r
5a9f73bf
ED
5376 Context->FormId = mCurrentFormId;\r
5377 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
7c6c064c
ED
5378\r
5379 //\r
5380 // Save the menu history data.\r
5381 //\r
5382 InitializeListHead(&Context->FormHistoryList);\r
5383 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
5384 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
5385 RemoveEntryList (&MenuList->Link);\r
5386\r
5387 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
5388 }\r
ce6d12cc 5389\r
5390 //\r
5391 // Insert to FormBrowser context list\r
5392 //\r
5393 InsertHeadList (&gBrowserContextList, &Context->Link);\r
5394}\r
5395\r
5396\r
5397/**\r
5398 Restore globals used by previous call to SendForm().\r
5399\r
5400**/\r
5401VOID\r
5402RestoreBrowserContext (\r
5403 VOID\r
5404 )\r
5405{\r
5406 LIST_ENTRY *Link;\r
5407 BROWSER_CONTEXT *Context;\r
7c6c064c 5408 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 5409\r
5410 ASSERT (gBrowserContextCount != 0);\r
5411 gBrowserContextCount--;\r
5412 if (gBrowserContextCount == 0) {\r
5413 //\r
5414 // This is not reentry of SendForm(), no context to restore\r
5415 //\r
5416 return;\r
5417 }\r
5418\r
5419 ASSERT (!IsListEmpty (&gBrowserContextList));\r
5420\r
5421 Link = GetFirstNode (&gBrowserContextList);\r
5422 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5423\r
5424 //\r
5425 // Restore FormBrowser context\r
5426 //\r
5a9f73bf 5427 gCurrentSelection = Context->Selection;\r
ce6d12cc 5428 gResetRequired = Context->ResetRequired;\r
7c6c064c
ED
5429 gExitRequired = Context->ExitRequired;\r
5430 mCurrentHiiHandle = Context->HiiHandle;\r
5a9f73bf
ED
5431 mCurrentFormId = Context->FormId;\r
5432 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
7c6c064c
ED
5433\r
5434 //\r
5435 // Restore the menu history data.\r
5436 //\r
5437 while (!IsListEmpty (&Context->FormHistoryList)) {\r
5438 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
5439 RemoveEntryList (&MenuList->Link);\r
5440\r
5441 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
5442 }\r
ce6d12cc 5443\r
5444 //\r
5445 // Remove from FormBrowser context list\r
5446 //\r
5447 RemoveEntryList (&Context->Link);\r
5448 gBS->FreePool (Context);\r
5449}\r
48a9d5f7
LG
5450\r
5451/**\r
5452 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
5453 \r
5454 @param Handle The Hii Handle.\r
5455 \r
5456 @return the found FormSet context. If no found, NULL will return.\r
5457\r
5458**/\r
5459FORM_BROWSER_FORMSET * \r
5460GetFormSetFromHiiHandle (\r
5461 EFI_HII_HANDLE Handle\r
5462 )\r
5463{\r
5464 LIST_ENTRY *Link;\r
5465 FORM_BROWSER_FORMSET *FormSet;\r
5466\r
5467 Link = GetFirstNode (&gBrowserFormSetList);\r
5468 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5469 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
5470 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5471 if (!ValidateFormSet(FormSet)) {\r
5472 continue;\r
5473 }\r
48a9d5f7
LG
5474 if (FormSet->HiiHandle == Handle) {\r
5475 return FormSet;\r
5476 }\r
48a9d5f7
LG
5477 }\r
5478 \r
5479 return NULL;\r
5480}\r
5481\r
5482/**\r
5483 Check whether the input HII handle is the FormSet that is being used.\r
5484 \r
5485 @param Handle The Hii Handle.\r
5486 \r
5487 @retval TRUE HII handle is being used.\r
5488 @retval FALSE HII handle is not being used.\r
5489\r
5490**/\r
5491BOOLEAN\r
5492IsHiiHandleInBrowserContext (\r
5493 EFI_HII_HANDLE Handle\r
5494 )\r
5495{\r
5496 LIST_ENTRY *Link;\r
5497 BROWSER_CONTEXT *Context;\r
5498\r
5499 //\r
5500 // HiiHandle is Current FormSet.\r
5501 //\r
7c6c064c 5502 if (mCurrentHiiHandle == Handle) {\r
48a9d5f7
LG
5503 return TRUE;\r
5504 }\r
5505\r
5506 //\r
5507 // Check whether HiiHandle is in BrowserContext.\r
5508 //\r
5509 Link = GetFirstNode (&gBrowserContextList);\r
5510 while (!IsNull (&gBrowserContextList, Link)) {\r
5511 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
7c6c064c 5512 if (Context->HiiHandle == Handle) {\r
48a9d5f7
LG
5513 //\r
5514 // HiiHandle is in BrowserContext\r
5515 //\r
5516 return TRUE;\r
5517 }\r
5518 Link = GetNextNode (&gBrowserContextList, Link);\r
5519 }\r
5520 \r
5521 return FALSE;\r
5522}\r
5523\r
7c6c064c
ED
5524/**\r
5525 Perform Password check. \r
5526 Passwork may be encrypted by driver that requires the specific check.\r
5527 \r
5528 @param Form Form where Password Statement is in.\r
5529 @param Statement Password statement\r
5530 @param PasswordString Password string to be checked. It may be NULL.\r
5531 NULL means to restore password.\r
5532 "" string can be used to checked whether old password does exist.\r
5533 \r
5534 @return Status Status of Password check.\r
5535**/\r
5536EFI_STATUS\r
5537EFIAPI\r
5538PasswordCheck (\r
5539 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
5540 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
5541 IN EFI_STRING PasswordString OPTIONAL\r
5542 )\r
5543{\r
5544 EFI_STATUS Status;\r
5545 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5546 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
5547 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
5548 FORM_BROWSER_STATEMENT *Question;\r
5549\r
5550 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
5551 Question = GetBrowserStatement(Statement);\r
5552 ASSERT (Question != NULL);\r
5553\r
5554 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
5555 if (ConfigAccess == NULL) {\r
5556 return EFI_UNSUPPORTED;\r
5557 }\r
5558 } else {\r
5559 if (PasswordString == NULL) {\r
5560 return EFI_SUCCESS;\r
5561 } \r
27582c41
ED
5562\r
5563 //\r
5564 // Check whether has preexisted password.\r
5565 //\r
5566 if (PasswordString[0] == 0) {\r
5567 if (*((CHAR16 *) Question->BufferValue) == 0) {\r
5568 return EFI_SUCCESS;\r
5569 } else {\r
5570 return EFI_NOT_READY;\r
5571 }\r
5572 }\r
5573\r
5574 //\r
5575 // Check whether the input password is same as preexisted password.\r
5576 //\r
7c6c064c
ED
5577 if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
5578 return EFI_SUCCESS;\r
5579 } else {\r
5580 return EFI_NOT_READY;\r
5581 }\r
5582 }\r
5583 \r
5584 //\r
5585 // Prepare password string in HII database\r
5586 //\r
5587 if (PasswordString != NULL) {\r
5588 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
5589 } else {\r
5590 IfrTypeValue.string = 0;\r
5591 }\r
5592\r
5593 //\r
5594 // Send password to Configuration Driver for validation\r
5595 //\r
5596 Status = ConfigAccess->Callback (\r
5597 ConfigAccess,\r
5598 EFI_BROWSER_ACTION_CHANGING,\r
5599 Question->QuestionId,\r
5600 Question->HiiValue.Type,\r
5601 &IfrTypeValue,\r
5602 &ActionRequest\r
5603 );\r
5604\r
5605 //\r
5606 // Remove password string from HII database\r
5607 //\r
5608 if (PasswordString != NULL) {\r
5609 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
5610 }\r
5611\r
5612 return Status;\r
5613}\r
5614\r
48a9d5f7
LG
5615/**\r
5616 Find the registered HotKey based on KeyData.\r
5617 \r
5618 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5619 information for the hot key.\r
5620\r
5621 @return The registered HotKey context. If no found, NULL will return.\r
5622**/\r
5623BROWSER_HOT_KEY *\r
5624GetHotKeyFromRegisterList (\r
5625 IN EFI_INPUT_KEY *KeyData\r
5626 )\r
5627{\r
5628 LIST_ENTRY *Link;\r
5629 BROWSER_HOT_KEY *HotKey;\r
5630\r
5631 Link = GetFirstNode (&gBrowserHotKeyList);\r
5632 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
5633 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
5634 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
5635 return HotKey;\r
5636 }\r
5637 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
5638 }\r
5639 \r
5640 return NULL;\r
5641}\r
5642\r
5643/**\r
5644 Configure what scope the hot key will impact.\r
5645 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
5646 If no scope is set, the default scope will be FormSet level.\r
5647 After all registered hot keys are removed, previous Scope can reset to another level.\r
5648 \r
5649 @param[in] Scope Scope level to be set. \r
5650 \r
5651 @retval EFI_SUCCESS Scope is set correctly.\r
5652 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
5653 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
5654\r
5655**/\r
5656EFI_STATUS\r
5657EFIAPI\r
5658SetScope (\r
5659 IN BROWSER_SETTING_SCOPE Scope\r
5660 )\r
5661{\r
5662 if (Scope >= MaxLevel) {\r
5663 return EFI_INVALID_PARAMETER;\r
5664 }\r
7c6c064c 5665\r
48a9d5f7
LG
5666 //\r
5667 // When no hot key registered in system or on the first setting,\r
5668 // Scope can be set.\r
5669 //\r
5670 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
5671 gBrowserSettingScope = Scope;\r
5672 mBrowserScopeFirstSet = FALSE;\r
5673 } else if (Scope != gBrowserSettingScope) {\r
5674 return EFI_UNSUPPORTED;\r
5675 }\r
5676\r
5677 return EFI_SUCCESS;\r
5678}\r
5679\r
5680/**\r
5681 Register the hot key with its browser action, or unregistered the hot key.\r
5682 Only support hot key that is not printable character (control key, function key, etc.).\r
5683 If the action value is zero, the hot key will be unregistered if it has been registered.\r
5684 If the same hot key has been registered, the new action and help string will override the previous ones.\r
5685 \r
5686 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5687 information for the hot key. Its type is EFI_INPUT_KEY to \r
5688 be supported by all ConsoleIn devices.\r
5689 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
5690 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
5691 @param[in] HelpString Help string that describes the hot key information.\r
5692 Its value may be NULL for the unregistered hot key.\r
5693 \r
5694 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
5695 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
5696 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
5697 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
5698**/\r
5699EFI_STATUS\r
5700EFIAPI\r
5701RegisterHotKey (\r
5702 IN EFI_INPUT_KEY *KeyData,\r
5703 IN UINT32 Action,\r
5704 IN UINT16 DefaultId,\r
5705 IN EFI_STRING HelpString OPTIONAL\r
5706 )\r
5707{\r
5708 BROWSER_HOT_KEY *HotKey;\r
5709\r
5710 //\r
5711 // Check input parameters.\r
5712 //\r
5713 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
5714 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
5715 return EFI_INVALID_PARAMETER;\r
5716 }\r
5717\r
5718 //\r
5719 // Check whether the input KeyData is in BrowserHotKeyList.\r
5720 //\r
5721 HotKey = GetHotKeyFromRegisterList (KeyData);\r
5722 \r
5723 //\r
5724 // Unregister HotKey\r
5725 //\r
5726 if (Action == BROWSER_ACTION_UNREGISTER) {\r
5727 if (HotKey != NULL) {\r
5728 //\r
5729 // The registered HotKey is found. \r
5730 // Remove it from List, and free its resource.\r
5731 //\r
5732 RemoveEntryList (&HotKey->Link);\r
5733 FreePool (HotKey->KeyData);\r
5734 FreePool (HotKey->HelpString);\r
5735 return EFI_SUCCESS;\r
5736 } else {\r
5737 //\r
5738 // The registered HotKey is not found. \r
5739 //\r
5740 return EFI_NOT_FOUND;\r
5741 }\r
5742 }\r
5743 \r
5744 //\r
5745 // Register HotKey into List.\r
5746 //\r
5747 if (HotKey == NULL) {\r
5748 //\r
5749 // Create new Key, and add it into List.\r
5750 //\r
5751 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
5752 ASSERT (HotKey != NULL);\r
5753 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
5754 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
5755 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
5756 }\r
5757\r
5758 //\r
5759 // Fill HotKey information.\r
5760 //\r
5761 HotKey->Action = Action;\r
5762 HotKey->DefaultId = DefaultId;\r
5763 if (HotKey->HelpString != NULL) {\r
5764 FreePool (HotKey->HelpString);\r
5765 }\r
5766 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
5767\r
5768 return EFI_SUCCESS;\r
5769}\r
5770\r
5771/**\r
5772 Register Exit handler function. \r
5773 When more than one handler function is registered, the latter one will override the previous one. \r
5774 When NULL handler is specified, the previous Exit handler will be unregistered. \r
5775 \r
5776 @param[in] Handler Pointer to handler function. \r
5777\r
5778**/\r
5779VOID\r
5780EFIAPI\r
5781RegiserExitHandler (\r
5782 IN EXIT_HANDLER Handler\r
5783 )\r
5784{\r
5785 ExitHandlerFunction = Handler;\r
5786 return;\r
5787}\r
5788\r
7c6c064c
ED
5789/**\r
5790 Check whether the browser data has been modified.\r
5791\r
5792 @retval TRUE Browser data is modified.\r
5793 @retval FALSE No browser data is modified.\r
5794\r
5795**/\r
5796BOOLEAN\r
5797EFIAPI\r
5798IsBrowserDataModified (\r
5799 VOID\r
5800 )\r
5801{\r
5802 LIST_ENTRY *Link;\r
5803 FORM_BROWSER_FORMSET *FormSet;\r
5804\r
7c6c064c
ED
5805 switch (gBrowserSettingScope) {\r
5806 case FormLevel:\r
27bace9b
ED
5807 if (gCurrentSelection == NULL) {\r
5808 return FALSE;\r
5809 }\r
7c6c064c
ED
5810 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
5811\r
5812 case FormSetLevel:\r
27bace9b
ED
5813 if (gCurrentSelection == NULL) {\r
5814 return FALSE;\r
5815 }\r
7c6c064c
ED
5816 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
5817\r
5818 case SystemLevel:\r
5819 Link = GetFirstNode (&gBrowserFormSetList);\r
5820 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5821 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
27bace9b
ED
5822 if (!ValidateFormSet(FormSet)) {\r
5823 continue;\r
5824 }\r
5825\r
7c6c064c
ED
5826 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
5827 return TRUE;\r
5828 }\r
5829 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5830 }\r
5831 return FALSE;\r
5832\r
5833 default:\r
5834 return FALSE;\r
5835 }\r
5836}\r
5837\r
5838/**\r
5839 Execute the action requested by the Action parameter.\r
5840\r
5841 @param[in] Action Execute the request action.\r
5842 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
5843\r
5844 @retval EFI_SUCCESS Execute the request action succss.\r
5845 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
5846\r
5847**/\r
5848EFI_STATUS \r
5849EFIAPI\r
5850ExecuteAction (\r
5851 IN UINT32 Action,\r
5852 IN UINT16 DefaultId\r
5853 )\r
5854{\r
27bace9b
ED
5855 EFI_STATUS Status;\r
5856 FORM_BROWSER_FORMSET *FormSet;\r
5857 FORM_BROWSER_FORM *Form;\r
7c6c064c 5858\r
27bace9b 5859 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
7c6c064c
ED
5860 return EFI_NOT_READY;\r
5861 }\r
5862\r
27bace9b
ED
5863 Status = EFI_SUCCESS;\r
5864 FormSet = NULL;\r
5865 Form = NULL;\r
5866 if (gBrowserSettingScope < SystemLevel) {\r
5867 FormSet = gCurrentSelection->FormSet;\r
5868 Form = gCurrentSelection->Form; \r
5869 }\r
7c6c064c
ED
5870\r
5871 //\r
5872 // Executet the discard action.\r
5873 //\r
5874 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
27bace9b 5875 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5876 if (EFI_ERROR (Status)) {\r
5877 return Status;\r
5878 }\r
5879 }\r
5880\r
5881 //\r
5882 // Executet the difault action.\r
5883 //\r
5884 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
27bace9b 5885 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
7c6c064c
ED
5886 if (EFI_ERROR (Status)) {\r
5887 return Status;\r
5888 }\r
892eccc8 5889 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5890 }\r
5891\r
5892 //\r
5893 // Executet the submit action.\r
5894 //\r
5895 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
27bace9b 5896 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5897 if (EFI_ERROR (Status)) {\r
5898 return Status;\r
5899 }\r
5900 }\r
5901\r
5902 //\r
5903 // Executet the reset action.\r
5904 //\r
5905 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
5906 gResetRequired = TRUE;\r
5907 }\r
5908\r
5909 //\r
5910 // Executet the exit action.\r
5911 //\r
5912 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
27bace9b 5913 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
5914 if (gBrowserSettingScope == SystemLevel) {\r
5915 if (ExitHandlerFunction != NULL) {\r
5916 ExitHandlerFunction ();\r
5917 }\r
5918 }\r
5919\r
5920 gExitRequired = TRUE;\r
5921 }\r
5922\r
5923 return Status;\r
5924}\r
5925\r
48a9d5f7
LG
5926/**\r
5927 Create reminder to let user to choose save or discard the changed browser data.\r
5928 Caller can use it to actively check the changed browser data.\r
5929\r
5930 @retval BROWSER_NO_CHANGES No browser data is changed.\r
5931 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
5932 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
27bace9b 5933 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
48a9d5f7
LG
5934\r
5935**/\r
5936UINT32\r
5937EFIAPI\r
5938SaveReminder (\r
5939 VOID\r
5940 )\r
5941{\r
5942 LIST_ENTRY *Link;\r
5943 FORM_BROWSER_FORMSET *FormSet;\r
5944 BOOLEAN IsDataChanged;\r
5945 UINT32 DataSavedAction;\r
27bace9b 5946 UINT32 ConfirmRet;\r
48a9d5f7
LG
5947\r
5948 DataSavedAction = BROWSER_NO_CHANGES;\r
5949 IsDataChanged = FALSE;\r
5950 Link = GetFirstNode (&gBrowserFormSetList);\r
5951 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5952 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
5953 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5954 if (!ValidateFormSet(FormSet)) {\r
5955 continue;\r
5956 }\r
7c6c064c 5957 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
48a9d5f7
LG
5958 IsDataChanged = TRUE;\r
5959 break;\r
5960 }\r
48a9d5f7
LG
5961 }\r
5962 \r
5963 //\r
5964 // No data is changed. No save is required. \r
5965 //\r
5966 if (!IsDataChanged) {\r
5967 return DataSavedAction;\r
5968 }\r
5969 \r
5970 //\r
7c6c064c 5971 // If data is changed, prompt user to save or discard it. \r
48a9d5f7 5972 //\r
48a9d5f7 5973 do {\r
27bace9b 5974 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
48a9d5f7 5975\r
27bace9b 5976 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
7c6c064c 5977 SubmitForm (NULL, NULL, SystemLevel);\r
27bace9b 5978 DataSavedAction = BROWSER_SAVE_CHANGES;\r
7c6c064c 5979 break;\r
27bace9b 5980 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
7c6c064c 5981 DiscardForm (NULL, NULL, SystemLevel);\r
27bace9b
ED
5982 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
5983 break;\r
5984 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
5985 DataSavedAction = BROWSER_KEEP_CURRENT;\r
7c6c064c
ED
5986 break;\r
5987 }\r
5988 } while (1);\r
48a9d5f7
LG
5989\r
5990 return DataSavedAction;\r
5991}\r
7da62bc0
ED
5992\r
5993/**\r
5994 Check whether the Reset Required for the browser\r
5995\r
5996 @retval TRUE Browser required to reset after exit.\r
5997 @retval FALSE Browser not need to reset after exit.\r
5998\r
5999**/\r
6000BOOLEAN\r
6001EFIAPI\r
6002IsResetRequired (\r
6003 VOID\r
6004 )\r
6005{\r
6006 return gResetRequired;\r
6007}\r
6008\r