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