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