]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdePkg: Refine the comments for FileHandleLib.
[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
1598 return Status;\r
1599 }\r
1600\r
1601 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1602 QuestionValue->date.Year = EfiTime.Year;\r
1603 QuestionValue->date.Month = EfiTime.Month;\r
1604 QuestionValue->date.Day = EfiTime.Day;\r
1605 } else {\r
1606 QuestionValue->time.Hour = EfiTime.Hour;\r
1607 QuestionValue->time.Minute = EfiTime.Minute;\r
1608 QuestionValue->time.Second = EfiTime.Second;\r
1609 }\r
1610 }\r
1611\r
1612 return EFI_SUCCESS;\r
1613 }\r
1614\r
1615 //\r
1616 // Question value is provided by EFI variable\r
1617 //\r
1618 StorageWidth = Question->StorageWidth;\r
1619 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1620 if (Question->BufferValue != NULL) {\r
1621 Dst = Question->BufferValue;\r
1622 } else {\r
1623 Dst = (UINT8 *) QuestionValue;\r
1624 }\r
1625\r
1626 Status = gRT->GetVariable (\r
1627 Question->VariableName,\r
1628 &Storage->Guid,\r
1629 NULL,\r
1630 &StorageWidth,\r
1631 Dst\r
1632 );\r
1633 //\r
1634 // Always return success, even this EFI variable doesn't exist\r
1635 //\r
1636 return EFI_SUCCESS;\r
1637 }\r
1638\r
1639 //\r
1640 // Question Value is provided by Buffer Storage or NameValue Storage\r
1641 //\r
1642 if (Question->BufferValue != NULL) {\r
1643 //\r
1644 // This Question is password or orderedlist\r
1645 //\r
1646 Dst = Question->BufferValue;\r
1647 } else {\r
1648 //\r
1649 // Other type of Questions\r
1650 //\r
1651 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1652 }\r
1653\r
cce6230f
ED
1654 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1655 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1656 IsBufferStorage = TRUE;\r
1657 } else {\r
1658 IsBufferStorage = FALSE;\r
1659 }\r
816a7110 1660 if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {\r
7936fb6a 1661 if (IsBufferStorage) {\r
816a7110
ED
1662 if (GetValueFrom == GetSetValueWithEditBuffer) {\r
1663 //\r
1664 // Copy from storage Edit buffer\r
1665 //\r
1666 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1667 } else {\r
1668 //\r
1669 // Copy from storage Edit buffer\r
1670 //\r
1671 CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1672 }\r
7936fb6a 1673 } else {\r
1b2bf3ca 1674 Value = NULL;\r
816a7110 1675 Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
7936fb6a 1676 if (EFI_ERROR (Status)) {\r
1677 return Status;\r
1678 }\r
d66e6c16 1679\r
1b2bf3ca 1680 ASSERT (Value != NULL);\r
7a9612ce 1681 Status = BufferToValue (Question, Value);\r
f4113e1f 1682 FreePool (Value);\r
7936fb6a 1683 }\r
1684 } else {\r
a35ecb75
ED
1685 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
1686 ASSERT (FormsetStorage != NULL);\r
7248790e
ED
1687 //\r
1688 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1689 // <ConfigHdr> + "&" + <VariableName>\r
1690 //\r
1691 if (IsBufferStorage) {\r
a35ecb75 1692 Length = StrLen (FormsetStorage->ConfigHdr);\r
7248790e
ED
1693 Length += StrLen (Question->BlockName);\r
1694 } else {\r
a35ecb75 1695 Length = StrLen (FormsetStorage->ConfigHdr);\r
7248790e
ED
1696 Length += StrLen (Question->VariableName) + 1;\r
1697 }\r
1698 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1699 ASSERT (ConfigRequest != NULL);\r
7936fb6a 1700\r
a35ecb75 1701 StrCpy (ConfigRequest, FormsetStorage->ConfigHdr);\r
7248790e
ED
1702 if (IsBufferStorage) {\r
1703 StrCat (ConfigRequest, Question->BlockName);\r
1704 } else {\r
1705 StrCat (ConfigRequest, L"&");\r
1706 StrCat (ConfigRequest, Question->VariableName);\r
1707 }\r
7936fb6a 1708\r
7248790e
ED
1709 //\r
1710 // Request current settings from Configuration Driver\r
1711 //\r
1712 Status = mHiiConfigRouting->ExtractConfig (\r
1713 mHiiConfigRouting,\r
1714 ConfigRequest,\r
1715 &Progress,\r
1716 &Result\r
1717 );\r
1718 FreePool (ConfigRequest);\r
1719 if (EFI_ERROR (Status)) {\r
1720 return Status;\r
1721 }\r
7936fb6a 1722\r
7248790e
ED
1723 //\r
1724 // Skip <ConfigRequest>\r
1725 //\r
1726 if (IsBufferStorage) {\r
1727 Value = StrStr (Result, L"&VALUE");\r
1728 if (Value == NULL) {\r
cce6230f
ED
1729 FreePool (Result);\r
1730 return EFI_NOT_FOUND;\r
1731 }\r
1732 //\r
7248790e 1733 // Skip "&VALUE"\r
cce6230f 1734 //\r
7248790e
ED
1735 Value = Value + 6;\r
1736 } else {\r
1737 Value = Result + Length;\r
1738 }\r
1739 if (*Value != '=') {\r
1740 FreePool (Result);\r
1741 return EFI_NOT_FOUND;\r
1742 }\r
1743 //\r
1744 // Skip '=', point to value\r
1745 //\r
1746 Value = Value + 1;\r
1747\r
7a9612ce 1748 Status = BufferToValue (Question, Value);\r
7248790e
ED
1749 if (EFI_ERROR (Status)) {\r
1750 FreePool (Result);\r
1751 return Status;\r
63d55bb9
LG
1752 }\r
1753\r
7936fb6a 1754 //\r
1755 // Synchronize Edit Buffer\r
1756 //\r
1757 if (IsBufferStorage) {\r
1758 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1759 } else {\r
7c6c064c 1760 SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
7936fb6a 1761 }\r
db40504e
ED
1762\r
1763 if (Result != NULL) {\r
1764 FreePool (Result);\r
1765 }\r
7936fb6a 1766 }\r
1767\r
1768 return Status;\r
1769}\r
1770\r
1771\r
1772/**\r
1773 Save Question Value to edit copy(cached) or Storage(uncached).\r
1774\r
1775 @param FormSet FormSet data structure.\r
1776 @param Form Form data structure.\r
1777 @param Question Pointer to the Question.\r
816a7110 1778 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.\r
7936fb6a 1779\r
1780 @retval EFI_SUCCESS The function completed successfully.\r
1781\r
1782**/\r
1783EFI_STATUS\r
1784SetQuestionValue (\r
1785 IN FORM_BROWSER_FORMSET *FormSet,\r
1786 IN FORM_BROWSER_FORM *Form,\r
1787 IN OUT FORM_BROWSER_STATEMENT *Question,\r
816a7110 1788 IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
7936fb6a 1789 )\r
1790{\r
1791 EFI_STATUS Status;\r
1792 BOOLEAN Enabled;\r
1793 BOOLEAN Pending;\r
1794 UINT8 *Src;\r
1795 EFI_TIME EfiTime;\r
1796 UINTN BufferLen;\r
1797 UINTN StorageWidth;\r
94f3aae7 1798 BROWSER_STORAGE *Storage;\r
a35ecb75 1799 FORMSET_STORAGE *FormsetStorage;\r
7936fb6a 1800 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1801 CHAR16 *ConfigResp;\r
1802 CHAR16 *Progress;\r
1803 CHAR16 *Value;\r
1804 UINTN Length;\r
1805 BOOLEAN IsBufferStorage;\r
1806 BOOLEAN IsString;\r
63d55bb9
LG
1807 UINT8 *TemBuffer;\r
1808 CHAR16 *TemName;\r
1809 CHAR16 *TemString;\r
1810 UINTN Index;\r
7c6c064c 1811 NAME_VALUE_NODE *Node;\r
7936fb6a 1812\r
1813 Status = EFI_SUCCESS;\r
7c6c064c 1814 Node = NULL;\r
7936fb6a 1815\r
816a7110
ED
1816 if (SetValueTo >= GetSetValueWithMax) {\r
1817 return EFI_INVALID_PARAMETER;\r
1818 }\r
1819\r
7936fb6a 1820 //\r
1821 // If Question value is provided by an Expression, then it is read only\r
1822 //\r
1823 if (Question->ValueExpression != NULL) {\r
1824 return Status;\r
1825 }\r
2573712e
LG
1826 \r
1827 //\r
1828 // Before set question value, evaluate its write expression.\r
1829 //\r
1830 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1831 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1832 if (EFI_ERROR (Status)) {\r
1833 return Status;\r
1834 }\r
1835 }\r
7936fb6a 1836\r
1837 //\r
1838 // Question value is provided by RTC\r
1839 //\r
1840 Storage = Question->Storage;\r
1841 QuestionValue = &Question->HiiValue.Value;\r
1842 if (Storage == NULL) {\r
1843 //\r
1844 // It's a Question without storage, or RTC date/time\r
1845 //\r
1846 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1847 //\r
1848 // Date and time define the same Flags bit\r
1849 //\r
1850 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1851 case QF_DATE_STORAGE_TIME:\r
1852 Status = gRT->GetTime (&EfiTime, NULL);\r
1853 break;\r
1854\r
1855 case QF_DATE_STORAGE_WAKEUP:\r
1856 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1857 break;\r
1858\r
1859 case QF_DATE_STORAGE_NORMAL:\r
1860 default:\r
1861 //\r
1862 // For date/time without storage\r
1863 //\r
1864 return EFI_SUCCESS;\r
1865 }\r
1866\r
1867 if (EFI_ERROR (Status)) {\r
1868 return Status;\r
1869 }\r
1870\r
1871 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1872 EfiTime.Year = QuestionValue->date.Year;\r
1873 EfiTime.Month = QuestionValue->date.Month;\r
1874 EfiTime.Day = QuestionValue->date.Day;\r
1875 } else {\r
1876 EfiTime.Hour = QuestionValue->time.Hour;\r
1877 EfiTime.Minute = QuestionValue->time.Minute;\r
1878 EfiTime.Second = QuestionValue->time.Second;\r
1879 }\r
1880\r
1881 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1882 Status = gRT->SetTime (&EfiTime);\r
1883 } else {\r
1884 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1885 }\r
1886 }\r
1887\r
1888 return Status;\r
1889 }\r
1890\r
1891 //\r
1892 // Question value is provided by EFI variable\r
1893 //\r
1894 StorageWidth = Question->StorageWidth;\r
1895 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1896 if (Question->BufferValue != NULL) {\r
1897 Src = Question->BufferValue;\r
1898 } else {\r
1899 Src = (UINT8 *) QuestionValue;\r
1900 }\r
1901\r
1902 Status = gRT->SetVariable (\r
1903 Question->VariableName,\r
1904 &Storage->Guid,\r
1905 Storage->Attributes,\r
1906 StorageWidth,\r
1907 Src\r
1908 );\r
1909 return Status;\r
1910 }\r
1911\r
1912 //\r
1913 // Question Value is provided by Buffer Storage or NameValue Storage\r
1914 //\r
1915 if (Question->BufferValue != NULL) {\r
1916 Src = Question->BufferValue;\r
1917 } else {\r
1918 Src = (UINT8 *) &Question->HiiValue.Value;\r
1919 }\r
1920\r
cce6230f
ED
1921 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1922 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1923 IsBufferStorage = TRUE;\r
1924 } else {\r
1925 IsBufferStorage = FALSE;\r
1926 }\r
7936fb6a 1927 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
816a7110
ED
1928\r
1929 if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {\r
1930 if (IsBufferStorage) {\r
1931 if (SetValueTo == GetSetValueWithEditBuffer) {\r
1932 //\r
1933 // Copy to storage edit buffer\r
1934 // \r
1935 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1936 } else if (SetValueTo == GetSetValueWithBuffer) {\r
1937 //\r
1938 // Copy to storage edit buffer\r
1939 // \r
1940 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
63d55bb9 1941 }\r
7936fb6a 1942 } else {\r
816a7110
ED
1943 if (IsString) {\r
1944 //\r
1945 // Allocate enough string buffer.\r
1946 //\r
1947 Value = NULL;\r
1948 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1949 Value = AllocateZeroPool (BufferLen);\r
1950 ASSERT (Value != NULL);\r
1951 //\r
1952 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1953 //\r
1954 TemName = (CHAR16 *) Src;\r
1955 TemString = Value;\r
1956 for (; *TemName != L'\0'; TemName++) {\r
1957 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1958 }\r
1959 } else {\r
1960 BufferLen = StorageWidth * 2 + 1;\r
1961 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1962 ASSERT (Value != NULL);\r
1963 //\r
1964 // Convert Buffer to Hex String\r
1965 //\r
1966 TemBuffer = Src + StorageWidth - 1;\r
1967 TemString = Value;\r
1968 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1969 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1970 }\r
63d55bb9 1971 }\r
7936fb6a 1972\r
7c6c064c 1973 Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
816a7110 1974 FreePool (Value);\r
7c6c064c
ED
1975 if (EFI_ERROR (Status)) {\r
1976 return Status;\r
1977 }\r
816a7110
ED
1978 }\r
1979 } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
7248790e
ED
1980 //\r
1981 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1982 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1983 //\r
1984 if (IsBufferStorage) {\r
1985 Length = StrLen (Question->BlockName) + 7;\r
1986 } else {\r
1987 Length = StrLen (Question->VariableName) + 2;\r
1988 }\r
1989 if (!IsBufferStorage && IsString) {\r
1990 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1991 } else {\r
1992 Length += (StorageWidth * 2);\r
1993 }\r
a35ecb75
ED
1994 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
1995 ASSERT (FormsetStorage != NULL);\r
1996 ConfigResp = AllocateZeroPool ((StrLen (FormsetStorage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
7248790e 1997 ASSERT (ConfigResp != NULL);\r
7936fb6a 1998\r
a35ecb75 1999 StrCpy (ConfigResp, FormsetStorage->ConfigHdr);\r
7248790e
ED
2000 if (IsBufferStorage) {\r
2001 StrCat (ConfigResp, Question->BlockName);\r
2002 StrCat (ConfigResp, L"&VALUE=");\r
2003 } else {\r
2004 StrCat (ConfigResp, L"&");\r
2005 StrCat (ConfigResp, Question->VariableName);\r
2006 StrCat (ConfigResp, L"=");\r
2007 }\r
cce6230f 2008\r
7248790e 2009 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 2010\r
7248790e 2011 if (!IsBufferStorage && IsString) {\r
7936fb6a 2012 //\r
7248790e 2013 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
7936fb6a 2014 //\r
7248790e
ED
2015 TemName = (CHAR16 *) Src;\r
2016 TemString = Value;\r
2017 for (; *TemName != L'\0'; TemName++) {\r
2018 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
63d55bb9 2019 }\r
7248790e 2020 } else {\r
63d55bb9 2021 //\r
7248790e 2022 // Convert Buffer to Hex String\r
63d55bb9 2023 //\r
7248790e
ED
2024 TemBuffer = Src + StorageWidth - 1;\r
2025 TemString = Value;\r
2026 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
2027 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
63d55bb9 2028 }\r
7248790e
ED
2029 }\r
2030\r
2031 //\r
2032 // Convert to lower char.\r
2033 //\r
2034 for (TemString = Value; *Value != L'\0'; Value++) {\r
2035 if (*Value >= L'A' && *Value <= L'Z') {\r
2036 *Value = (CHAR16) (*Value - L'A' + L'a');\r
7936fb6a 2037 }\r
2038 }\r
7248790e
ED
2039\r
2040 //\r
2041 // Submit Question Value to Configuration Driver\r
2042 //\r
2043 Status = mHiiConfigRouting->RouteConfig (\r
2044 mHiiConfigRouting,\r
2045 ConfigResp,\r
2046 &Progress\r
2047 );\r
2048 if (EFI_ERROR (Status)) {\r
2049 FreePool (ConfigResp);\r
2050 return Status;\r
2051 }\r
2052 FreePool (ConfigResp);\r
2053 \r
7936fb6a 2054 //\r
cce6230f 2055 // Sync storage, from editbuffer to buffer.\r
7936fb6a 2056 //\r
cce6230f 2057 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
7936fb6a 2058 }\r
2059\r
2060 return Status;\r
2061}\r
2062\r
2063\r
2064/**\r
7c6c064c 2065 Perform nosubmitif check for a Form.\r
7936fb6a 2066\r
2067 @param FormSet FormSet data structure.\r
2068 @param Form Form data structure.\r
2069 @param Question The Question to be validated.\r
7c6c064c 2070 @param Type Validation type: NoSubmit\r
7936fb6a 2071\r
2072 @retval EFI_SUCCESS Form validation pass.\r
2073 @retval other Form validation failed.\r
2074\r
2075**/\r
2076EFI_STATUS\r
2077ValidateQuestion (\r
2078 IN FORM_BROWSER_FORMSET *FormSet,\r
2079 IN FORM_BROWSER_FORM *Form,\r
2080 IN FORM_BROWSER_STATEMENT *Question,\r
2081 IN UINTN Type\r
2082 )\r
2083{\r
2084 EFI_STATUS Status;\r
2085 LIST_ENTRY *Link;\r
2086 LIST_ENTRY *ListHead;\r
7936fb6a 2087 FORM_EXPRESSION *Expression;\r
bfae1330
ED
2088 UINT32 BrowserStatus;\r
2089 CHAR16 *ErrorStr;\r
2090\r
2091 BrowserStatus = BROWSER_SUCCESS;\r
2092 ErrorStr = NULL;\r
2093\r
2094 switch (Type) {\r
2095 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2096 ListHead = &Question->InconsistentListHead;\r
2097 break;\r
7936fb6a 2098\r
bfae1330
ED
2099 case EFI_HII_EXPRESSION_WARNING_IF:\r
2100 ListHead = &Question->WarningListHead;\r
2101 break;\r
2102\r
2103 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
7936fb6a 2104 ListHead = &Question->NoSubmitListHead;\r
bfae1330
ED
2105 break;\r
2106\r
2107 default:\r
2108 ASSERT (FALSE);\r
7936fb6a 2109 return EFI_UNSUPPORTED;\r
2110 }\r
2111\r
2112 Link = GetFirstNode (ListHead);\r
2113 while (!IsNull (ListHead, Link)) {\r
2114 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
2115\r
2116 //\r
2117 // Evaluate the expression\r
2118 //\r
2119 Status = EvaluateExpression (FormSet, Form, Expression);\r
2120 if (EFI_ERROR (Status)) {\r
2121 return Status;\r
2122 }\r
2123\r
e6106e89 2124 if (IsTrue (&Expression->Result)) {\r
bfae1330
ED
2125 switch (Type) {\r
2126 case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
2127 BrowserStatus = BROWSER_INCONSISTENT_IF;\r
2128 break;\r
2129\r
2130 case EFI_HII_EXPRESSION_WARNING_IF:\r
2131 BrowserStatus = BROWSER_WARNING_IF;\r
2132 break;\r
2133\r
2134 case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
2135 BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
2136 //\r
2137 // This code only used to compatible with old display engine,\r
2138 // New display engine will not use this field.\r
2139 //\r
2140 if (Expression->Error != 0) {\r
2141 ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
7c6c064c 2142 }\r
bfae1330
ED
2143 break;\r
2144\r
2145 default:\r
2146 ASSERT (FALSE);\r
2147 break;\r
7936fb6a 2148 }\r
2149\r
4d4deaac
ED
2150 if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
2151 //\r
2152 // If in system submit process and for no_submit_if check, not popup this error message.\r
2153 // Will process this fail again later in not system submit process.\r
2154 //\r
2155 PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
2156 }\r
bfae1330
ED
2157\r
2158 if (ErrorStr != NULL) {\r
2159 FreePool (ErrorStr);\r
2160 }\r
2161\r
2162 if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
2163 return EFI_SUCCESS;\r
2164 } else {\r
2165 return EFI_NOT_READY;\r
2166 }\r
7936fb6a 2167 }\r
2168\r
2169 Link = GetNextNode (ListHead, Link);\r
2170 }\r
2171\r
2172 return EFI_SUCCESS;\r
2173}\r
2174\r
bfae1330
ED
2175/**\r
2176 Perform question check. \r
2177 \r
2178 If one question has more than one check, process form high priority to low. \r
2179 Only one error info will be popup.\r
2180\r
2181 @param FormSet FormSet data structure.\r
2182 @param Form Form data structure.\r
2183 @param Question The Question to be validated.\r
2184\r
2185 @retval EFI_SUCCESS Form validation pass.\r
2186 @retval other Form validation failed.\r
2187\r
2188**/\r
2189EFI_STATUS\r
2190ValueChangedValidation (\r
2191 IN FORM_BROWSER_FORMSET *FormSet,\r
2192 IN FORM_BROWSER_FORM *Form,\r
2193 IN FORM_BROWSER_STATEMENT *Question\r
2194 )\r
2195{\r
2196 EFI_STATUS Status;\r
2197\r
2198 Status = EFI_SUCCESS;\r
2199\r
2200 //\r
2201 // Do the inconsistentif check.\r
2202 //\r
2203 if (!IsListEmpty (&Question->InconsistentListHead)) {\r
2204 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
2205 if (EFI_ERROR (Status)) {\r
2206 return Status;\r
2207 }\r
2208 }\r
2209\r
2210 //\r
2211 // Do the warningif check.\r
2212 //\r
2213 if (!IsListEmpty (&Question->WarningListHead)) {\r
2214 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
2215 }\r
2216\r
2217 return Status;\r
2218}\r
7936fb6a 2219\r
2220/**\r
5adb8db7 2221 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 2222\r
2223 @param FormSet FormSet data structure.\r
b18e7050 2224 @param CurrentForm Current input form data structure.\r
4d4deaac 2225 @param Statement The statement for this check.\r
7936fb6a 2226\r
2227 @retval EFI_SUCCESS Form validation pass.\r
2228 @retval other Form validation failed.\r
2229\r
2230**/\r
2231EFI_STATUS\r
2232NoSubmitCheck (\r
4d4deaac
ED
2233 IN FORM_BROWSER_FORMSET *FormSet,\r
2234 IN OUT FORM_BROWSER_FORM **CurrentForm,\r
2235 OUT FORM_BROWSER_STATEMENT **Statement\r
7936fb6a 2236 )\r
2237{\r
2238 EFI_STATUS Status;\r
2239 LIST_ENTRY *Link;\r
2240 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
2241 FORM_BROWSER_FORM *Form;\r
2242 LIST_ENTRY *LinkForm;\r
7936fb6a 2243\r
5adb8db7
LG
2244 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
2245 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
2246 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
2247 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
2248\r
4d4deaac 2249 if (*CurrentForm != NULL && *CurrentForm != Form) {\r
b18e7050
ED
2250 continue;\r
2251 }\r
7936fb6a 2252\r
5adb8db7
LG
2253 Link = GetFirstNode (&Form->StatementListHead);\r
2254 while (!IsNull (&Form->StatementListHead, Link)) {\r
2255 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
5adb8db7
LG
2256 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2257 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
2258 if (*CurrentForm == NULL) {\r
2259 *CurrentForm = Form;\r
2260 }\r
2261 if (Statement != NULL) {\r
2262 *Statement = Question;\r
2263 }\r
5adb8db7
LG
2264 return Status;\r
2265 }\r
2266\r
2267 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 2268 }\r
7936fb6a 2269 }\r
2270\r
2271 return EFI_SUCCESS;\r
2272}\r
2273\r
7936fb6a 2274/**\r
b18e7050
ED
2275 Fill storage's edit copy with settings requested from Configuration Driver.\r
2276\r
7c6c064c
ED
2277 @param Storage The storage which need to sync.\r
2278 @param ConfigRequest The config request string which used to sync storage.\r
cce6230f
ED
2279 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2280 editbuffer to buffer\r
2281 if TRUE, copy the editbuffer to the buffer.\r
2282 if FALSE, copy the buffer to the editbuffer.\r
b18e7050
ED
2283\r
2284 @retval EFI_SUCCESS The function completed successfully.\r
2285\r
2286**/\r
2287EFI_STATUS\r
7c6c064c 2288SynchronizeStorage (\r
7c6c064c
ED
2289 OUT BROWSER_STORAGE *Storage,\r
2290 IN CHAR16 *ConfigRequest,\r
2291 IN BOOLEAN SyncOrRestore\r
b18e7050
ED
2292 )\r
2293{\r
2294 EFI_STATUS Status;\r
2295 EFI_STRING Progress;\r
2296 EFI_STRING Result;\r
2297 UINTN BufferSize;\r
2298 LIST_ENTRY *Link;\r
2299 NAME_VALUE_NODE *Node;\r
cce6230f
ED
2300 UINT8 *Src;\r
2301 UINT8 *Dst;\r
b18e7050
ED
2302\r
2303 Status = EFI_SUCCESS;\r
2304 Result = NULL;\r
25361615 2305\r
7c6c064c
ED
2306 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2307 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
2308 BufferSize = Storage->Size;\r
cce6230f
ED
2309\r
2310 if (SyncOrRestore) {\r
7c6c064c
ED
2311 Src = Storage->EditBuffer;\r
2312 Dst = Storage->Buffer;\r
cce6230f 2313 } else {\r
7c6c064c
ED
2314 Src = Storage->Buffer;\r
2315 Dst = Storage->EditBuffer;\r
cce6230f
ED
2316 }\r
2317\r
7c6c064c
ED
2318 if (ConfigRequest != NULL) {\r
2319 Status = mHiiConfigRouting->BlockToConfig(\r
2320 mHiiConfigRouting,\r
2321 ConfigRequest,\r
2322 Src,\r
2323 BufferSize,\r
2324 &Result,\r
2325 &Progress\r
2326 );\r
2327 if (EFI_ERROR (Status)) {\r
2328 return Status;\r
2329 }\r
b18e7050 2330\r
7c6c064c
ED
2331 Status = mHiiConfigRouting->ConfigToBlock (\r
2332 mHiiConfigRouting,\r
2333 Result,\r
2334 Dst,\r
2335 &BufferSize,\r
2336 &Progress\r
2337 );\r
2338 if (Result != NULL) {\r
2339 FreePool (Result);\r
2340 }\r
2341 } else {\r
2342 CopyMem (Dst, Src, BufferSize);\r
b18e7050 2343 }\r
7c6c064c
ED
2344 } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2345 Link = GetFirstNode (&Storage->NameValueListHead);\r
2346 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
b18e7050
ED
2347 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2348\r
7c6c064c
ED
2349 if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
2350 (ConfigRequest == NULL)) {\r
cce6230f
ED
2351 if (SyncOrRestore) {\r
2352 NewStringCpy (&Node->Value, Node->EditValue);\r
2353 } else {\r
2354 NewStringCpy (&Node->EditValue, Node->Value);\r
b18e7050 2355 }\r
b18e7050
ED
2356 }\r
2357\r
7c6c064c 2358 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
b18e7050
ED
2359 }\r
2360 }\r
2361\r
2362 return Status;\r
2363}\r
2364\r
816a7110
ED
2365/**\r
2366 When discard the question value, call the callback function with Changed type\r
2367 to inform the hii driver.\r
2368\r
2369 @param FormSet FormSet data structure.\r
2370 @param Form Form data structure.\r
2371\r
2372**/\r
2373VOID\r
2374SendDiscardInfoToDriver (\r
2375 IN FORM_BROWSER_FORMSET *FormSet,\r
2376 IN FORM_BROWSER_FORM *Form\r
2377 )\r
2378{\r
2379 LIST_ENTRY *Link;\r
2380 FORM_BROWSER_STATEMENT *Question;\r
816a7110
ED
2381 EFI_IFR_TYPE_VALUE *TypeValue;\r
2382 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2383\r
70f1d5e7
ED
2384 if (FormSet->ConfigAccess == NULL) {\r
2385 return;\r
2386 }\r
2387\r
816a7110
ED
2388 Link = GetFirstNode (&Form->StatementListHead);\r
2389 while (!IsNull (&Form->StatementListHead, Link)) {\r
2390 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2391 Link = GetNextNode (&Form->StatementListHead, Link);\r
2392\r
2393 if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2394 continue;\r
2395 }\r
2396\r
e213ae45
ED
2397 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
2398 continue;\r
2399 }\r
2400\r
816a7110
ED
2401 if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
2402 continue;\r
2403 }\r
2404\r
7c6c064c 2405 if (!Question->ValueChanged) {\r
816a7110
ED
2406 continue;\r
2407 }\r
2408\r
737adca3
ED
2409 //\r
2410 // Restore the question value before call the CHANGED callback type.\r
2411 //\r
2412 GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
2413\r
816a7110
ED
2414 if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
2415 TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
2416 } else {\r
2417 TypeValue = &Question->HiiValue.Value;\r
2418 }\r
2419\r
2420 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2421 FormSet->ConfigAccess->Callback (\r
2422 FormSet->ConfigAccess,\r
2423 EFI_BROWSER_ACTION_CHANGED,\r
2424 Question->QuestionId,\r
2425 Question->HiiValue.Type,\r
2426 TypeValue,\r
2427 &ActionRequest\r
2428 );\r
2429 }\r
2430}\r
b18e7050 2431\r
938baa1f 2432/**\r
dcca25d1 2433 Validate the HiiHandle.\r
938baa1f 2434\r
dcca25d1 2435 @param HiiHandle The input HiiHandle which need to validate.\r
938baa1f
ED
2436\r
2437 @retval TRUE The handle is validate.\r
2438 @retval FALSE The handle is invalidate.\r
2439\r
2440**/\r
2441BOOLEAN\r
93551a01
ED
2442ValidateHiiHandle (\r
2443 EFI_HII_HANDLE HiiHandle\r
938baa1f
ED
2444 )\r
2445{\r
2446 EFI_HII_HANDLE *HiiHandles;\r
2447 UINTN Index;\r
2448 BOOLEAN Find;\r
2449\r
93551a01
ED
2450 if (HiiHandle == NULL) {\r
2451 return FALSE;\r
2452 }\r
2453\r
938baa1f 2454 Find = FALSE;\r
93551a01 2455\r
938baa1f
ED
2456 HiiHandles = HiiGetHiiHandles (NULL);\r
2457 ASSERT (HiiHandles != NULL);\r
2458\r
938baa1f 2459 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
93551a01 2460 if (HiiHandles[Index] == HiiHandle) {\r
938baa1f
ED
2461 Find = TRUE;\r
2462 break;\r
2463 }\r
2464 }\r
2465\r
93551a01
ED
2466 FreePool (HiiHandles);\r
2467\r
2468 return Find;\r
2469}\r
2470\r
2471/**\r
2472 Validate the FormSet. If the formset is not validate, remove it from the list.\r
2473\r
2474 @param FormSet The input FormSet which need to validate.\r
2475\r
2476 @retval TRUE The handle is validate.\r
2477 @retval FALSE The handle is invalidate.\r
2478\r
2479**/\r
2480BOOLEAN\r
2481ValidateFormSet (\r
2482 FORM_BROWSER_FORMSET *FormSet\r
2483 )\r
2484{\r
2485 BOOLEAN Find;\r
2486\r
2487 ASSERT (FormSet != NULL);\r
2488\r
2489 Find = ValidateHiiHandle(FormSet->HiiHandle);\r
275ea01e
ED
2490 //\r
2491 // Should not remove the formset which is being used.\r
2492 //\r
2493 if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
0a6f8af5 2494 CleanBrowserStorage(FormSet);\r
938baa1f
ED
2495 RemoveEntryList (&FormSet->Link);\r
2496 DestroyFormSet (FormSet);\r
2497 }\r
2498\r
938baa1f
ED
2499 return Find;\r
2500}\r
7c6c064c
ED
2501/**\r
2502 Check whether need to enable the reset flag in form level.\r
2503 Also clean all ValueChanged flag in question.\r
2504\r
2505 @param SetFlag Whether need to set the Reset Flag.\r
4d4deaac 2506 @param FormSet FormSet data structure.\r
7c6c064c
ED
2507 @param Form Form data structure.\r
2508\r
2509**/\r
2510VOID\r
2511UpdateFlagForForm (\r
2512 IN BOOLEAN SetFlag,\r
4d4deaac 2513 IN FORM_BROWSER_FORMSET *FormSet,\r
7c6c064c
ED
2514 IN FORM_BROWSER_FORM *Form\r
2515 )\r
2516{\r
2517 LIST_ENTRY *Link;\r
2518 FORM_BROWSER_STATEMENT *Question;\r
4d4deaac 2519 BOOLEAN OldValue;\r
7c6c064c 2520\r
7c6c064c
ED
2521 Link = GetFirstNode (&Form->StatementListHead);\r
2522 while (!IsNull (&Form->StatementListHead, Link)) {\r
2523 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4d4deaac 2524 Link = GetNextNode (&Form->StatementListHead, Link);\r
7c6c064c 2525\r
4d4deaac
ED
2526 if (!Question->ValueChanged) {\r
2527 continue;\r
7c6c064c 2528 }\r
4d4deaac
ED
2529\r
2530 OldValue = Question->ValueChanged;\r
2531\r
2532 //\r
2533 // Compare the buffer and editbuffer data to see whether the data has been saved.\r
2534 //\r
2535 Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
2536\r
2537 //\r
2538 // Only the changed data has been saved, then need to set the reset flag.\r
2539 //\r
f2e7732e
ED
2540 if (SetFlag && OldValue && !Question->ValueChanged) {\r
2541 if ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
2542 gResetRequired = TRUE;\r
2543 }\r
2544\r
2545 if ((Question->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
2546 gFlagReconnect = TRUE;\r
2547 }\r
4d4deaac 2548 } \r
7c6c064c
ED
2549 }\r
2550}\r
2551\r
2552/**\r
2553 Check whether need to enable the reset flag.\r
2554 Also clean ValueChanged flag for all statements.\r
2555\r
2556 Form level or formset level, only one.\r
2557 \r
2558 @param SetFlag Whether need to set the Reset Flag.\r
2559 @param FormSet FormSet data structure.\r
2560 @param Form Form data structure.\r
2561\r
2562**/\r
2563VOID\r
2564ValueChangeResetFlagUpdate (\r
2565 IN BOOLEAN SetFlag,\r
2566 IN FORM_BROWSER_FORMSET *FormSet,\r
2567 IN FORM_BROWSER_FORM *Form \r
2568 )\r
2569{\r
2570 FORM_BROWSER_FORM *CurrentForm;\r
2571 LIST_ENTRY *Link;\r
2572\r
7c6c064c 2573 if (Form != NULL) {\r
4d4deaac 2574 UpdateFlagForForm(SetFlag, FormSet, Form);\r
7c6c064c
ED
2575 return;\r
2576 }\r
2577\r
2578 Link = GetFirstNode (&FormSet->FormListHead);\r
2579 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2580 CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2581 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2582\r
4d4deaac 2583 UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
7c6c064c
ED
2584 }\r
2585}\r
938baa1f 2586\r
4d4deaac
ED
2587/**\r
2588 Base on the return Progress string to find the form. \r
2589 \r
2590 Base on the first return Offset/Width (Name) string to find the form\r
2591 which keep this string.\r
2592\r
2593 @param FormSet FormSet data structure.\r
2594 @param Storage Storage which has this Progress string.\r
2595 @param Progress The Progress string which has the first fail string.\r
2596 @param RetForm The return form for this progress string.\r
2597 @param RetQuestion The return question for the error progress string.\r
2598\r
2599 @retval TRUE Find the error form and statement for this error progress string.\r
2600 @retval FALSE Not find the error form.\r
2601\r
2602**/\r
2603BOOLEAN\r
2604FindQuestionFromProgress (\r
2605 IN FORM_BROWSER_FORMSET *FormSet,\r
2606 IN BROWSER_STORAGE *Storage,\r
2607 IN EFI_STRING Progress,\r
2608 OUT FORM_BROWSER_FORM **RetForm,\r
2609 OUT FORM_BROWSER_STATEMENT **RetQuestion\r
2610 )\r
2611{\r
2612 LIST_ENTRY *Link;\r
2613 LIST_ENTRY *LinkStorage;\r
2614 LIST_ENTRY *LinkStatement;\r
2615 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
2616 FORM_BROWSER_FORM *Form;\r
2617 EFI_STRING EndStr;\r
2618 FORM_BROWSER_STATEMENT *Statement;\r
2619\r
2620 ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
2621\r
2622 ConfigInfo = NULL;\r
2623 *RetForm = NULL;\r
2624 *RetQuestion = NULL;\r
2625\r
2626 //\r
2627 // Skip the first "&" or the ConfigHdr part.\r
2628 //\r
2629 if (*Progress == '&') {\r
2630 Progress++;\r
2631 } else {\r
2632 //\r
2633 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2634 //\r
2635 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2636 //\r
2637 // For Name/Value type, Skip the ConfigHdr part.\r
2638 //\r
2639 EndStr = StrStr (Progress, L"PATH=");\r
e77d2f9d 2640 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2641 while (*EndStr != '&') {\r
2642 EndStr++;\r
2643 }\r
2644\r
2645 *EndStr = '\0';\r
2646 } else {\r
2647 //\r
2648 // For Buffer type, Skip the ConfigHdr part.\r
2649 //\r
2650 EndStr = StrStr (Progress, L"&OFFSET=");\r
e77d2f9d 2651 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2652 *EndStr = '\0';\r
2653 }\r
2654\r
2655 Progress = EndStr + 1;\r
2656 }\r
2657\r
2658 //\r
2659 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
2660 //\r
2661 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2662 //\r
2663 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
2664 // here, just keep the "Fred" string.\r
2665 //\r
2666 EndStr = StrStr (Progress, L"=");\r
e77d2f9d 2667 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2668 *EndStr = '\0';\r
2669 } else {\r
2670 //\r
2671 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
2672 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
2673 //\r
2674 EndStr = StrStr (Progress, L"&VALUE=");\r
e77d2f9d 2675 ASSERT (EndStr != NULL);\r
4d4deaac
ED
2676 *EndStr = '\0';\r
2677 }\r
2678\r
2679 //\r
2680 // Search in the form list.\r
2681 //\r
2682 Link = GetFirstNode (&FormSet->FormListHead);\r
2683 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2684 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2685 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2686\r
2687 //\r
2688 // Search in the ConfigReqeust list in this form.\r
2689 //\r
2690 LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
2691 while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
2692 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
2693 LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
2694\r
2695 if (Storage != ConfigInfo->Storage) {\r
2696 continue;\r
2697 }\r
2698\r
2699 if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
2700 //\r
2701 // Find the OffsetWidth string in this form.\r
2702 //\r
2703 *RetForm = Form;\r
2704 break;\r
2705 }\r
2706 }\r
2707\r
2708 if (*RetForm != NULL) {\r
2709 LinkStatement = GetFirstNode (&Form->StatementListHead);\r
2710 while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
2711 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
2712 LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
2713\r
2714 if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
2715 *RetQuestion = Statement;\r
2716 break;\r
2717 }\r
a35ecb75
ED
2718\r
2719 if (Statement->VariableName != NULL && StrStr (Statement->VariableName, Progress) != NULL) {\r
2720 *RetQuestion = Statement;\r
2721 break;\r
2722 }\r
4d4deaac
ED
2723 }\r
2724 }\r
2725\r
2726 if (*RetForm != NULL) {\r
2727 break;\r
2728 }\r
2729 }\r
2730\r
2731 //\r
2732 // restore the OffsetWidth string to the original format.\r
2733 //\r
2734 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2735 *EndStr = '=';\r
2736 } else {\r
2737 *EndStr = '&';\r
2738 }\r
2739\r
5039b444 2740 return (BOOLEAN) (*RetForm != NULL);\r
4d4deaac
ED
2741}\r
2742\r
2743/**\r
2744 Popup an save error info and get user input.\r
2745\r
2746 @param TitleId The form title id.\r
2747 @param HiiHandle The hii handle for this package.\r
2748\r
2749 @retval UINT32 The user select option for the save fail.\r
2750 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2751**/\r
2752UINT32\r
2753ConfirmSaveFail (\r
2754 IN EFI_STRING_ID TitleId,\r
2755 IN EFI_HII_HANDLE HiiHandle\r
2756 )\r
2757{\r
2758 CHAR16 *FormTitle;\r
2759 CHAR16 *StringBuffer;\r
2760 UINT32 RetVal;\r
2761\r
2762 FormTitle = GetToken (TitleId, HiiHandle);\r
2763\r
2764 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2765 ASSERT (StringBuffer != NULL);\r
2766\r
2767 UnicodeSPrint (\r
2768 StringBuffer, \r
2769 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2770 L"Submit Fail For Form: %s.", \r
2771 FormTitle\r
2772 );\r
2773\r
2774 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
2775\r
2776 FreePool (StringBuffer);\r
2777 FreePool (FormTitle);\r
2778\r
2779 return RetVal;\r
2780}\r
2781\r
2782/**\r
2783 Popup an NO_SUBMIT_IF error info and get user input.\r
2784\r
2785 @param TitleId The form title id.\r
2786 @param HiiHandle The hii handle for this package.\r
2787\r
2788 @retval UINT32 The user select option for the save fail.\r
2789 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
2790**/\r
2791UINT32\r
2792ConfirmNoSubmitFail (\r
2793 IN EFI_STRING_ID TitleId,\r
2794 IN EFI_HII_HANDLE HiiHandle\r
2795 )\r
2796{\r
2797 CHAR16 *FormTitle;\r
2798 CHAR16 *StringBuffer;\r
2799 UINT32 RetVal;\r
2800\r
2801 FormTitle = GetToken (TitleId, HiiHandle);\r
2802\r
2803 StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
2804 ASSERT (StringBuffer != NULL);\r
2805\r
2806 UnicodeSPrint (\r
2807 StringBuffer, \r
2808 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
2809 L"NO_SUBMIT_IF error For Form: %s.", \r
2810 FormTitle\r
2811 );\r
2812\r
2813 RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
2814\r
2815 FreePool (StringBuffer);\r
2816 FreePool (FormTitle);\r
2817\r
2818 return RetVal;\r
2819}\r
2820\r
b18e7050 2821/**\r
48a9d5f7 2822 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 2823\r
2824 @param FormSet FormSet data structure.\r
2825 @param Form Form data structure.\r
48a9d5f7 2826 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
2827\r
2828 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2829 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
2830\r
2831**/\r
2832EFI_STATUS\r
2833DiscardForm (\r
2834 IN FORM_BROWSER_FORMSET *FormSet,\r
2835 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2836 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
2837 )\r
2838{\r
48a9d5f7
LG
2839 LIST_ENTRY *Link;\r
2840 FORMSET_STORAGE *Storage;\r
b18e7050 2841 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
6e74560f
ED
2842 FORM_BROWSER_FORMSET *LocalFormSet;\r
2843 FORM_BROWSER_FORMSET *OldFormSet;\r
b18e7050 2844\r
48a9d5f7
LG
2845 //\r
2846 // Check the supported setting level.\r
2847 //\r
2848 if (SettingScope >= MaxLevel) {\r
2849 return EFI_UNSUPPORTED;\r
2850 }\r
b18e7050 2851\r
7c6c064c 2852 if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
48a9d5f7
LG
2853 ConfigInfo = NULL;\r
2854 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2855 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2856 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2857 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 2858\r
48a9d5f7
LG
2859 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2860 continue;\r
2861 }\r
2862\r
2863 //\r
2864 // Skip if there is no RequestElement\r
2865 //\r
2866 if (ConfigInfo->ElementCount == 0) {\r
2867 continue;\r
b18e7050
ED
2868 }\r
2869\r
48a9d5f7
LG
2870 //\r
2871 // Prepare <ConfigResp>\r
2872 //\r
4d4deaac 2873 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
816a7110 2874\r
816a7110
ED
2875 //\r
2876 // Call callback with Changed type to inform the driver.\r
2877 //\r
2878 SendDiscardInfoToDriver (FormSet, Form);\r
2879 }\r
2880\r
4d4deaac 2881 ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
7c6c064c 2882 } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
f1660263 2883\r
48a9d5f7
LG
2884 //\r
2885 // Discard Buffer storage or Name/Value storage\r
2886 //\r
2887 Link = GetFirstNode (&FormSet->StorageListHead);\r
2888 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2889 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2890 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2891\r
94f3aae7 2892 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
48a9d5f7
LG
2893 continue;\r
2894 }\r
2895\r
b18e7050 2896 //\r
48a9d5f7 2897 // Skip if there is no RequestElement\r
b18e7050 2898 //\r
48a9d5f7
LG
2899 if (Storage->ElementCount == 0) {\r
2900 continue;\r
2901 }\r
b18e7050 2902\r
4d4deaac 2903 SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
48a9d5f7 2904 }\r
f1660263
ED
2905\r
2906 Link = GetFirstNode (&FormSet->FormListHead);\r
2907 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2908 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2909 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2910 \r
2911 //\r
2912 // Call callback with Changed type to inform the driver.\r
2913 //\r
2914 SendDiscardInfoToDriver (FormSet, Form);\r
2915 }\r
b18e7050 2916\r
7c6c064c 2917 ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
48a9d5f7
LG
2918 } else if (SettingScope == SystemLevel) {\r
2919 //\r
2920 // System Level Discard.\r
2921 //\r
6e74560f
ED
2922 OldFormSet = mSystemLevelFormSet;\r
2923\r
48a9d5f7
LG
2924 //\r
2925 // Discard changed value for each FormSet in the maintain list.\r
2926 //\r
2927 Link = GetFirstNode (&gBrowserFormSetList);\r
2928 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2929 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 2930 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
2931 if (!ValidateFormSet(LocalFormSet)) {\r
2932 continue;\r
2933 }\r
6e74560f
ED
2934\r
2935 mSystemLevelFormSet = LocalFormSet;\r
2936\r
938baa1f 2937 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
48a9d5f7 2938 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 2939 //\r
48a9d5f7 2940 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 2941 //\r
0a6f8af5 2942 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7
LG
2943 RemoveEntryList (&LocalFormSet->Link);\r
2944 DestroyFormSet (LocalFormSet);\r
b18e7050 2945 }\r
b18e7050 2946 }\r
6e74560f
ED
2947\r
2948 mSystemLevelFormSet = OldFormSet;\r
b18e7050
ED
2949 }\r
2950\r
2951 return EFI_SUCCESS; \r
2952}\r
2953\r
2954/**\r
4d4deaac 2955 Submit data for a form.\r
b18e7050
ED
2956\r
2957 @param FormSet FormSet data structure.\r
2958 @param Form Form data structure.\r
7936fb6a 2959\r
2960 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2961 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2962\r
2963**/\r
2964EFI_STATUS\r
4d4deaac 2965SubmitForForm (\r
7936fb6a 2966 IN FORM_BROWSER_FORMSET *FormSet,\r
4d4deaac 2967 IN FORM_BROWSER_FORM *Form\r
7936fb6a 2968 )\r
2969{\r
2970 EFI_STATUS Status;\r
2971 LIST_ENTRY *Link;\r
2972 EFI_STRING ConfigResp;\r
2973 EFI_STRING Progress;\r
94f3aae7 2974 BROWSER_STORAGE *Storage;\r
b18e7050 2975 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 2976\r
4d4deaac
ED
2977 if (!IsNvUpdateRequiredForForm (Form)) {\r
2978 return EFI_SUCCESS;\r
2979 }\r
2980\r
2981 Status = NoSubmitCheck (FormSet, &Form, NULL);\r
2982 if (EFI_ERROR (Status)) {\r
2983 return Status;\r
2984 }\r
2985\r
2986 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2987 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2988 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2989 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
2990\r
2991 Storage = ConfigInfo->Storage;\r
2992 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2993 continue;\r
2994 }\r
2995\r
2996 //\r
2997 // Skip if there is no RequestElement\r
2998 //\r
2999 if (ConfigInfo->ElementCount == 0) {\r
3000 continue;\r
3001 }\r
3002\r
3003 //\r
3004 // 1. Prepare <ConfigResp>\r
3005 //\r
3006 Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
3007 if (EFI_ERROR (Status)) {\r
3008 return Status;\r
3009 }\r
3010\r
3011 //\r
3012 // 2. Set value to hii config routine protocol.\r
3013 //\r
3014 Status = mHiiConfigRouting->RouteConfig (\r
3015 mHiiConfigRouting,\r
3016 ConfigResp,\r
3017 &Progress\r
3018 );\r
3019 FreePool (ConfigResp);\r
3020\r
3021 if (EFI_ERROR (Status)) {\r
3022 InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
3023 continue;\r
3024 }\r
3025\r
3026 //\r
3027 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
3028 //\r
3029 SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
3030 }\r
3031\r
48a9d5f7 3032 //\r
4d4deaac 3033 // 4. Process the save failed storage.\r
48a9d5f7 3034 //\r
4d4deaac
ED
3035 if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3036 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3037 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3038 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3039 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3040 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3041\r
3042 SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
3043\r
3044 Status = EFI_SUCCESS;\r
3045 }\r
3046 } else {\r
3047 Status = EFI_UNSUPPORTED;\r
3048 }\r
3049\r
3050 //\r
3051 // Free Form save fail list.\r
3052 //\r
3053 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3054 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3055 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
3056 RemoveEntryList (&ConfigInfo->SaveFailLink);\r
3057 }\r
48a9d5f7
LG
3058 }\r
3059\r
7936fb6a 3060 //\r
4d4deaac 3061 // 5. Update the NV flag.\r
7936fb6a 3062 //\r
4d4deaac
ED
3063 ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
3064\r
3065 return Status;\r
3066}\r
3067\r
3068/**\r
3069 Submit data for a formset.\r
3070\r
3071 @param FormSet FormSet data structure.\r
3072 @param SkipProcessFail Whether skip to process the save failed storage.\r
3073 If submit formset is called when do system level save, \r
3074 set this value to true and process the failed formset \r
3075 together. \r
3076 if submit formset is called when do formset level save,\r
3077 set the value to false and process the failed storage\r
3078 right after process all storages for this formset.\r
3079\r
3080 @retval EFI_SUCCESS The function completed successfully.\r
3081 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3082\r
3083**/\r
3084EFI_STATUS\r
3085SubmitForFormSet (\r
3086 IN FORM_BROWSER_FORMSET *FormSet,\r
3087 IN BOOLEAN SkipProcessFail\r
3088 )\r
3089{\r
3090 EFI_STATUS Status;\r
3091 LIST_ENTRY *Link;\r
3092 EFI_STRING ConfigResp;\r
3093 EFI_STRING Progress;\r
3094 BROWSER_STORAGE *Storage;\r
3095 FORMSET_STORAGE *FormSetStorage;\r
3096 FORM_BROWSER_FORM *Form;\r
3097 BOOLEAN HasInserted;\r
3098 FORM_BROWSER_STATEMENT *Question;\r
3099\r
3100 HasInserted = FALSE;\r
3101\r
3102 if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
3103 return EFI_SUCCESS;\r
b18e7050 3104 }\r
4d4deaac
ED
3105\r
3106 Form = NULL; \r
3107 Status = NoSubmitCheck (FormSet, &Form, &Question);\r
7936fb6a 3108 if (EFI_ERROR (Status)) {\r
4d4deaac
ED
3109 if (SkipProcessFail) {\r
3110 //\r
3111 // Process NO_SUBMIT check first, so insert it at head.\r
3112 //\r
3113 FormSet->SaveFailForm = Form;\r
3114 FormSet->SaveFailStatement = Question;\r
3115 InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3116 }\r
3117\r
7936fb6a 3118 return Status;\r
3119 }\r
3120\r
4d4deaac
ED
3121 Form = NULL;\r
3122 Question = NULL;\r
3123 //\r
3124 // Submit Buffer storage or Name/Value storage\r
3125 //\r
3126 Link = GetFirstNode (&FormSet->StorageListHead);\r
3127 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3128 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3129 Storage = FormSetStorage->BrowserStorage;\r
3130 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
7936fb6a 3131\r
4d4deaac
ED
3132 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3133 continue;\r
3134 }\r
7936fb6a 3135\r
4d4deaac
ED
3136 //\r
3137 // Skip if there is no RequestElement\r
3138 //\r
3139 if (FormSetStorage->ElementCount == 0) {\r
3140 continue;\r
3141 }\r
7936fb6a 3142\r
4d4deaac
ED
3143 //\r
3144 // 1. Prepare <ConfigResp>\r
3145 //\r
3146 Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
3147 if (EFI_ERROR (Status)) {\r
3148 return Status;\r
3149 }\r
b18e7050 3150\r
4d4deaac
ED
3151 //\r
3152 // 2. Send <ConfigResp> to Routine config Protocol.\r
3153 //\r
3154 Status = mHiiConfigRouting->RouteConfig (\r
3155 mHiiConfigRouting,\r
3156 ConfigResp,\r
3157 &Progress\r
3158 );\r
3159 if (EFI_ERROR (Status)) {\r
3160 InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
3161 if (!HasInserted) {\r
3162 //\r
3163 // Call submit formset for system level, save the formset info\r
3164 // and process later.\r
3165 //\r
3166 FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
3167 ASSERT (Form != NULL && Question != NULL);\r
3168 FormSet->SaveFailForm = Form;\r
3169 FormSet->SaveFailStatement = Question;\r
3170 if (SkipProcessFail) {\r
3171 InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
3172 }\r
3173 HasInserted = TRUE;\r
b18e7050 3174 }\r
7248790e 3175\r
b18e7050 3176 FreePool (ConfigResp);\r
4d4deaac 3177 continue;\r
7936fb6a 3178 }\r
3179\r
4d4deaac 3180 FreePool (ConfigResp);\r
cce6230f 3181 //\r
4d4deaac 3182 // 3. Config success, update storage shadow Buffer\r
7936fb6a 3183 //\r
4d4deaac
ED
3184 SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
3185 }\r
b18e7050 3186\r
4d4deaac
ED
3187 //\r
3188 // 4. Has save fail storage need to handle.\r
3189 //\r
3190 if (Form != NULL) {\r
3191 if (!SkipProcessFail) {\r
b18e7050 3192 //\r
4d4deaac 3193 // If not in system level, just handl the save failed storage here.\r
b18e7050 3194 //\r
4d4deaac
ED
3195 if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
3196 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3197 while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
3198 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3199 Storage = FormSetStorage->BrowserStorage;\r
3200 Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
b18e7050 3201\r
4d4deaac
ED
3202 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3203\r
3204 Status = EFI_SUCCESS;\r
3205 }\r
3206 } else {\r
3207 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3208\r
3209 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3210 gCurrentSelection->Handle = FormSet->HiiHandle;\r
3211 CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
3212 gCurrentSelection->FormId = Form->FormId;\r
3213 gCurrentSelection->QuestionId = Question->QuestionId;\r
3214\r
3215 Status = EFI_UNSUPPORTED;\r
7936fb6a 3216 }\r
b18e7050 3217\r
7248790e 3218 //\r
4d4deaac 3219 // Free FormSet save fail list.\r
7248790e 3220 //\r
4d4deaac
ED
3221 while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
3222 Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
3223 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
3224 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
b18e7050 3225 }\r
4d4deaac 3226 } else {\r
b18e7050 3227 //\r
4d4deaac 3228 // If in system level, just return error and handle the failed formset later.\r
b18e7050 3229 //\r
4d4deaac
ED
3230 Status = EFI_UNSUPPORTED;\r
3231 }\r
3232 }\r
3233\r
3234 //\r
3235 // 5. Update the NV flag.\r
3236 // \r
3237 ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
3238\r
3239 return Status;\r
3240}\r
3241\r
3242/**\r
3243 Submit data for all formsets.\r
3244\r
3245 @retval EFI_SUCCESS The function completed successfully.\r
3246 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3247\r
3248**/\r
3249EFI_STATUS\r
3250SubmitForSystem (\r
3251 VOID\r
3252 )\r
3253{\r
3254 EFI_STATUS Status;\r
3255 LIST_ENTRY *Link;\r
3256 LIST_ENTRY *StorageLink;\r
4d4deaac
ED
3257 FORMSET_STORAGE *FormSetStorage;\r
3258 FORM_BROWSER_FORM *Form;\r
3259 FORM_BROWSER_FORMSET *LocalFormSet;\r
3260 UINT32 UserSelection;\r
3261 FORM_BROWSER_STATEMENT *Question;\r
3262\r
3263 mSystemSubmit = TRUE;\r
3264 Link = GetFirstNode (&gBrowserFormSetList);\r
3265 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3266 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3267 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3268 if (!ValidateFormSet(LocalFormSet)) {\r
3269 continue;\r
3270 }\r
3271\r
3272 Status = SubmitForFormSet (LocalFormSet, TRUE);\r
3273 if (EFI_ERROR (Status)) {\r
3274 continue;\r
7936fb6a 3275 }\r
7936fb6a 3276\r
cce6230f 3277 //\r
4d4deaac
ED
3278 // Remove maintain backup list after save except for the current using FormSet.\r
3279 // \r
3280 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
3281 CleanBrowserStorage(LocalFormSet);\r
3282 RemoveEntryList (&LocalFormSet->Link);\r
3283 DestroyFormSet (LocalFormSet);\r
3284 }\r
3285 }\r
3286 mSystemSubmit = FALSE;\r
3287\r
3288 Status = EFI_SUCCESS;\r
3289\r
3290 //\r
3291 // Process the save failed formsets.\r
3292 //\r
3293 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3294 while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
3295 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3296 Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
3297\r
3298 if (!ValidateFormSet(LocalFormSet)) {\r
3299 continue;\r
3300 }\r
3301\r
3302 Form = LocalFormSet->SaveFailForm;\r
3303 Question= LocalFormSet->SaveFailStatement;\r
48a9d5f7
LG
3304\r
3305 //\r
4d4deaac 3306 // Confirm with user, get user input.\r
48a9d5f7 3307 //\r
4d4deaac
ED
3308 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3309 //\r
3310 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
3311 //\r
3312 UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3313 } else {\r
3314 UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
3315 }\r
3316\r
3317 if (UserSelection == BROWSER_ACTION_DISCARD) {\r
3318 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3319 StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
3320 while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
3321 FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
4d4deaac
ED
3322 StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
3323\r
3324 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3325 }\r
3326 } else {\r
3327 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3328 while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
3329 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
4d4deaac
ED
3330 StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
3331\r
3332 SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
3333 }\r
938baa1f 3334 }\r
4d4deaac 3335\r
48a9d5f7 3336 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
0a6f8af5 3337 CleanBrowserStorage(LocalFormSet);\r
48a9d5f7 3338 RemoveEntryList (&LocalFormSet->Link);\r
4d4deaac 3339 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
48a9d5f7 3340 DestroyFormSet (LocalFormSet);\r
4d4deaac
ED
3341 } else {\r
3342 ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
48a9d5f7 3343 }\r
4d4deaac
ED
3344 } else {\r
3345 if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3346 NoSubmitCheck (LocalFormSet, &Form, &Question);\r
3347 }\r
3348\r
3349 UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
3350\r
3351 gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
3352 gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
3353 CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
3354 gCurrentSelection->FormId = Form->FormId;\r
3355 gCurrentSelection->QuestionId = Question->QuestionId;\r
3356\r
3357 Status = EFI_UNSUPPORTED;\r
3358 break;\r
48a9d5f7 3359 }\r
7936fb6a 3360 }\r
3361\r
4d4deaac
ED
3362 //\r
3363 // Clean the list which will not process.\r
3364 //\r
3365 while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
3366 Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
3367 LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
3368 RemoveEntryList (&LocalFormSet->SaveFailLink);\r
3369\r
3370 while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
3371 StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
3372 FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
3373 RemoveEntryList (&FormSetStorage->SaveFailLink);\r
3374 }\r
3375 }\r
3376\r
3377 return Status;\r
3378}\r
3379\r
3380/**\r
3381 Submit data based on the input Setting level (Form, FormSet or System).\r
3382\r
3383 @param FormSet FormSet data structure.\r
3384 @param Form Form data structure.\r
3385 @param SettingScope Setting Scope for Submit action.\r
3386\r
3387 @retval EFI_SUCCESS The function completed successfully.\r
3388 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
3389\r
3390**/\r
3391EFI_STATUS\r
3392SubmitForm (\r
3393 IN FORM_BROWSER_FORMSET *FormSet,\r
3394 IN FORM_BROWSER_FORM *Form,\r
3395 IN BROWSER_SETTING_SCOPE SettingScope\r
3396 )\r
3397{\r
3398 EFI_STATUS Status;\r
3399\r
3400 switch (SettingScope) {\r
3401 case FormLevel:\r
3402 Status = SubmitForForm(FormSet, Form);\r
3403 break;\r
3404\r
3405 case FormSetLevel:\r
3406 Status = SubmitForFormSet (FormSet, FALSE);\r
3407 break;\r
3408\r
3409 case SystemLevel:\r
3410 Status = SubmitForSystem ();\r
3411 break;\r
3412\r
3413 default:\r
3414 Status = EFI_UNSUPPORTED;\r
3415 break;\r
3416 }\r
3417\r
3418 return Status;\r
7936fb6a 3419}\r
3420\r
ee31d1be 3421/**\r
7a9612ce
ED
3422 Converts the unicode character of the string from uppercase to lowercase.\r
3423 This is a internal function.\r
ee31d1be 3424\r
7a9612ce 3425 @param ConfigString String to be converted\r
ee31d1be
ED
3426\r
3427**/\r
7a9612ce
ED
3428VOID\r
3429EFIAPI\r
3430HiiToLower (\r
3431 IN EFI_STRING ConfigString\r
ee31d1be
ED
3432 )\r
3433{\r
7a9612ce
ED
3434 EFI_STRING String;\r
3435 BOOLEAN Lower;\r
ee31d1be 3436\r
7a9612ce 3437 ASSERT (ConfigString != NULL);\r
ee31d1be
ED
3438\r
3439 //\r
7a9612ce 3440 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
ee31d1be 3441 //\r
7a9612ce
ED
3442 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
3443 if (*String == L'=') {\r
3444 Lower = TRUE;\r
3445 } else if (*String == L'&') {\r
3446 Lower = FALSE;\r
3447 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
3448 *String = (CHAR16) (*String - L'A' + L'a');\r
3449 }\r
ee31d1be 3450 }\r
7a9612ce 3451}\r
ee31d1be 3452\r
7a9612ce
ED
3453/**\r
3454 Find the point in the ConfigResp string for this question.\r
3455\r
3456 @param Question The question.\r
3457 @param ConfigResp Get ConfigResp string.\r
3458\r
3459 @retval point to the offset where is for this question.\r
3460\r
3461**/\r
3462CHAR16 *\r
3463GetOffsetFromConfigResp (\r
3464 IN FORM_BROWSER_STATEMENT *Question,\r
3465 IN CHAR16 *ConfigResp\r
3466 )\r
3467{\r
3468 CHAR16 *RequestElement;\r
3469 CHAR16 *BlockData;\r
ee31d1be
ED
3470\r
3471 //\r
7a9612ce 3472 // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
ee31d1be 3473 //\r
7a9612ce
ED
3474 if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3475 RequestElement = StrStr (ConfigResp, Question->VariableName);\r
3476 if (RequestElement != NULL) {\r
3477 //\r
3478 // Skip the "VariableName=" field.\r
3479 //\r
3480 RequestElement += StrLen (Question->VariableName) + 1;\r
3481 }\r
ee31d1be 3482\r
7a9612ce 3483 return RequestElement;\r
ee31d1be
ED
3484 }\r
3485\r
3486 //\r
7a9612ce 3487 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
ee31d1be 3488 //\r
7a9612ce 3489\r
ee31d1be 3490 //\r
7a9612ce 3491 // 1. Directly use Question->BlockName to find.\r
ee31d1be 3492 //\r
7a9612ce
ED
3493 RequestElement = StrStr (ConfigResp, Question->BlockName);\r
3494 if (RequestElement != NULL) {\r
3495 //\r
3496 // Skip the "Question->BlockName&VALUE=" field.\r
3497 //\r
3498 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
3499 return RequestElement;\r
7248790e 3500 }\r
7a9612ce 3501 \r
ee31d1be 3502 //\r
7a9612ce 3503 // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
ee31d1be 3504 //\r
7a9612ce
ED
3505 BlockData = AllocateCopyPool (StrSize(Question->BlockName), Question->BlockName);\r
3506 ASSERT (BlockData != NULL);\r
3507 HiiToLower (BlockData);\r
3508 RequestElement = StrStr (ConfigResp, BlockData);\r
3509 FreePool (BlockData);\r
3510\r
3511 if (RequestElement != NULL) {\r
ee31d1be 3512 //\r
7a9612ce 3513 // Skip the "Question->BlockName&VALUE=" field.\r
ee31d1be 3514 //\r
7a9612ce 3515 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
ee31d1be 3516 }\r
7a9612ce
ED
3517\r
3518 return RequestElement;\r
3519}\r
3520\r
3521/**\r
3522 Get Question default value from AltCfg string.\r
3523\r
3524 @param FormSet The form set.\r
3525 @param Form The form\r
3526 @param Question The question.\r
3527\r
3528 @retval EFI_SUCCESS Question is reset to default value.\r
3529\r
3530**/\r
3531EFI_STATUS\r
3532GetDefaultValueFromAltCfg (\r
3533 IN FORM_BROWSER_FORMSET *FormSet,\r
3534 IN FORM_BROWSER_FORM *Form,\r
3535 IN OUT FORM_BROWSER_STATEMENT *Question\r
3536 )\r
3537{ \r
3538 BROWSER_STORAGE *Storage;\r
3539 FORMSET_STORAGE *FormSetStorage;\r
3540 CHAR16 *ConfigResp;\r
3541 CHAR16 *Value;\r
3542 LIST_ENTRY *Link;\r
3543 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
3544\r
3545 Storage = Question->Storage;\r
3546 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3547 return EFI_NOT_FOUND;\r
ee31d1be 3548 }\r
ee31d1be
ED
3549\r
3550 //\r
7a9612ce
ED
3551 // Try to get AltCfg string from form. If not found it, then\r
3552 // try to get it from formset.\r
ee31d1be 3553 //\r
7a9612ce
ED
3554 ConfigResp = NULL;\r
3555 Link = GetFirstNode (&Form->ConfigRequestHead);\r
3556 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
3557 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
3558 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
ee31d1be 3559\r
7a9612ce
ED
3560 if (Storage == ConfigInfo->Storage) {\r
3561 ConfigResp = ConfigInfo->ConfigAltResp;\r
3562 break;\r
ee31d1be 3563 }\r
7a9612ce
ED
3564 }\r
3565\r
3566 if (ConfigResp == NULL) {\r
3567 Link = GetFirstNode (&FormSet->StorageListHead);\r
3568 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3569 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
3570 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3571\r
3572 if (Storage == FormSetStorage->BrowserStorage) {\r
3573 ConfigResp = FormSetStorage->ConfigAltResp;\r
3574 break;\r
25361615
ED
3575 }\r
3576 }\r
3577 }\r
b9feb4bd 3578\r
7a9612ce
ED
3579 if (ConfigResp == NULL) {\r
3580 return EFI_NOT_FOUND;\r
7c6c064c
ED
3581 }\r
3582\r
7a9612ce
ED
3583 Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
3584 if (Value == NULL) {\r
3585 return EFI_NOT_FOUND;\r
7c6c064c
ED
3586 }\r
3587\r
7a9612ce 3588 return BufferToValue (Question, Value);\r
7c6c064c
ED
3589}\r
3590\r
3591/**\r
3592 Get default Id value used for browser.\r
3593\r
3594 @param DefaultId The default id value used by hii.\r
3595\r
3596 @retval Browser used default value.\r
3597\r
3598**/\r
3599INTN\r
3600GetDefaultIdForCallBack (\r
3601 UINTN DefaultId\r
3602 )\r
3603{ \r
3604 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3605 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
3606 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3607 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
3608 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
3609 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
3610 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
3611 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
3612 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
3613 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
3614 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
3615 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
3616 } else {\r
3617 return -1;\r
3618 }\r
3619}\r
3620\r
3621\r
3622\r
3623/**\r
3624 Return data element in an Array by its Index.\r
3625\r
3626 @param Array The data array.\r
3627 @param Type Type of the data in this array.\r
3628 @param Index Zero based index for data in this array.\r
3629\r
3630 @retval Value The data to be returned\r
3631\r
3632**/\r
3633UINT64\r
3634GetArrayData (\r
3635 IN VOID *Array,\r
3636 IN UINT8 Type,\r
3637 IN UINTN Index\r
3638 )\r
3639{\r
3640 UINT64 Data;\r
3641\r
3642 ASSERT (Array != NULL);\r
3643\r
3644 Data = 0;\r
3645 switch (Type) {\r
3646 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3647 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
3648 break;\r
3649\r
3650 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3651 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
3652 break;\r
3653\r
3654 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3655 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
3656 break;\r
3657\r
3658 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3659 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
3660 break;\r
3661\r
3662 default:\r
3663 break;\r
3664 }\r
3665\r
3666 return Data;\r
3667}\r
3668\r
3669\r
3670/**\r
3671 Set value of a data element in an Array by its Index.\r
3672\r
3673 @param Array The data array.\r
3674 @param Type Type of the data in this array.\r
3675 @param Index Zero based index for data in this array.\r
3676 @param Value The value to be set.\r
3677\r
3678**/\r
3679VOID\r
3680SetArrayData (\r
3681 IN VOID *Array,\r
3682 IN UINT8 Type,\r
3683 IN UINTN Index,\r
3684 IN UINT64 Value\r
3685 )\r
3686{\r
3687\r
3688 ASSERT (Array != NULL);\r
b9feb4bd 3689\r
7c6c064c
ED
3690 switch (Type) {\r
3691 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3692 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
3693 break;\r
25361615 3694\r
7c6c064c
ED
3695 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3696 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
3697 break;\r
3698\r
3699 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3700 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
3701 break;\r
3702\r
3703 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3704 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
3705 break;\r
3706\r
3707 default:\r
3708 break;\r
3709 }\r
ee31d1be
ED
3710}\r
3711\r
3712/**\r
7c6c064c 3713 Search an Option of a Question by its value.\r
ee31d1be 3714\r
7c6c064c
ED
3715 @param Question The Question\r
3716 @param OptionValue Value for Option to be searched.\r
ee31d1be 3717\r
7c6c064c
ED
3718 @retval Pointer Pointer to the found Option.\r
3719 @retval NULL Option not found.\r
ee31d1be
ED
3720\r
3721**/\r
7c6c064c
ED
3722QUESTION_OPTION *\r
3723ValueToOption (\r
3724 IN FORM_BROWSER_STATEMENT *Question,\r
3725 IN EFI_HII_VALUE *OptionValue\r
ee31d1be 3726 )\r
7c6c064c
ED
3727{\r
3728 LIST_ENTRY *Link;\r
3729 QUESTION_OPTION *Option;\r
3730 INTN Result;\r
3731\r
3732 Link = GetFirstNode (&Question->OptionListHead);\r
3733 while (!IsNull (&Question->OptionListHead, Link)) {\r
3734 Option = QUESTION_OPTION_FROM_LINK (Link);\r
3735\r
3736 if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
3737 //\r
3738 // Check the suppressif condition, only a valid option can be return.\r
3739 //\r
3740 if ((Option->SuppressExpression == NULL) ||\r
3741 ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
3742 return Option;\r
3743 }\r
3744 }\r
3745\r
3746 Link = GetNextNode (&Question->OptionListHead, Link);\r
ee31d1be 3747 }\r
7c6c064c
ED
3748\r
3749 return NULL;\r
ee31d1be 3750}\r
7936fb6a 3751\r
7c6c064c 3752\r
7936fb6a 3753/**\r
3754 Reset Question to its default value.\r
3755\r
3756 @param FormSet The form set.\r
3757 @param Form The form.\r
3758 @param Question The question.\r
3759 @param DefaultId The Class of the default.\r
3760\r
3761 @retval EFI_SUCCESS Question is reset to default value.\r
3762\r
3763**/\r
3764EFI_STATUS\r
3765GetQuestionDefault (\r
3766 IN FORM_BROWSER_FORMSET *FormSet,\r
3767 IN FORM_BROWSER_FORM *Form,\r
3768 IN FORM_BROWSER_STATEMENT *Question,\r
3769 IN UINT16 DefaultId\r
3770 )\r
3771{\r
3772 EFI_STATUS Status;\r
3773 LIST_ENTRY *Link;\r
3774 QUESTION_DEFAULT *Default;\r
3775 QUESTION_OPTION *Option;\r
3776 EFI_HII_VALUE *HiiValue;\r
3777 UINT8 Index;\r
086cd2c8 3778 EFI_STRING StrValue;\r
ee31d1be
ED
3779 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3780 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
3781 INTN Action;\r
061d5462 3782 CHAR16 *NewString;\r
7936fb6a 3783\r
48a9d5f7 3784 Status = EFI_NOT_FOUND;\r
086cd2c8 3785 StrValue = NULL;\r
7936fb6a 3786\r
3787 //\r
3788 // Statement don't have storage, skip them\r
3789 //\r
3790 if (Question->QuestionId == 0) {\r
3791 return Status;\r
3792 }\r
3793\r
3794 //\r
ee31d1be
ED
3795 // There are Five ways to specify default value for a Question:\r
3796 // 1, use call back function (highest priority)\r
3797 // 2, use ExtractConfig function\r
3798 // 3, use nested EFI_IFR_DEFAULT \r
3799 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
3800 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 3801 //\r
3802 HiiValue = &Question->HiiValue;\r
3803\r
ee31d1be
ED
3804 //\r
3805 // Get Question defaut value from call back function.\r
3806 //\r
3807 ConfigAccess = FormSet->ConfigAccess;\r
3808 Action = GetDefaultIdForCallBack (DefaultId);\r
3809 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
3810 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
3811 Status = ConfigAccess->Callback (\r
3812 ConfigAccess,\r
3813 Action,\r
3814 Question->QuestionId,\r
3815 HiiValue->Type,\r
3816 &HiiValue->Value,\r
3817 &ActionRequest\r
3818 );\r
3819 if (!EFI_ERROR (Status)) {\r
061d5462
ED
3820 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3821 NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
3822 ASSERT (NewString != NULL);\r
3823\r
3824 ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
3825 if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
3826 CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
3827 } else {\r
3828 CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
3829 }\r
3830\r
3831 FreePool (NewString);\r
3832 }\r
ee31d1be
ED
3833 return Status;\r
3834 }\r
3835 }\r
3836\r
3837 //\r
3838 // Get default value from altcfg string.\r
3839 //\r
3840 if (ConfigAccess != NULL) { \r
7a9612ce 3841 Status = GetDefaultValueFromAltCfg(FormSet, Form, Question);\r
ee31d1be
ED
3842 if (!EFI_ERROR (Status)) {\r
3843 return Status;\r
3844 }\r
3845 }\r
3846\r
7936fb6a 3847 //\r
3848 // EFI_IFR_DEFAULT has highest priority\r
3849 //\r
3850 if (!IsListEmpty (&Question->DefaultListHead)) {\r
3851 Link = GetFirstNode (&Question->DefaultListHead);\r
3852 while (!IsNull (&Question->DefaultListHead, Link)) {\r
3853 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
3854\r
3855 if (Default->DefaultId == DefaultId) {\r
3856 if (Default->ValueExpression != NULL) {\r
3857 //\r
3858 // Default is provided by an Expression, evaluate it\r
3859 //\r
3860 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
3861 if (EFI_ERROR (Status)) {\r
3862 return Status;\r
3863 }\r
3864\r
901ba0e7
ED
3865 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
3866 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
3867 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
3868 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
3869 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
3870 } else {\r
3871 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
3872 Question->HiiValue.BufferLen = Question->StorageWidth;\r
3873 }\r
3874 FreePool (Default->ValueExpression->Result.Buffer);\r
3875 }\r
3876 HiiValue->Type = Default->ValueExpression->Result.Type;\r
3877 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 3878 } else {\r
3879 //\r
3880 // Default value is embedded in EFI_IFR_DEFAULT\r
3881 //\r
0b567d18
ED
3882 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
3883 ASSERT (HiiValue->Buffer != NULL);\r
3884 CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
3885 } else {\r
3886 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
3887 }\r
7936fb6a 3888 }\r
3889\r
086cd2c8
LG
3890 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
3891 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
3892 if (StrValue == NULL) {\r
3893 return EFI_NOT_FOUND;\r
3894 }\r
ba944801
ED
3895 if (Question->StorageWidth > StrSize (StrValue)) {\r
3896 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
3897 } else {\r
3898 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
3899 }\r
086cd2c8
LG
3900 }\r
3901\r
7936fb6a 3902 return EFI_SUCCESS;\r
3903 }\r
3904\r
3905 Link = GetNextNode (&Question->DefaultListHead, Link);\r
3906 }\r
3907 }\r
3908\r
3909 //\r
3910 // EFI_ONE_OF_OPTION\r
3911 //\r
3912 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
3913 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3914 //\r
3915 // OneOfOption could only provide Standard and Manufacturing default\r
3916 //\r
3917 Link = GetFirstNode (&Question->OptionListHead);\r
3918 while (!IsNull (&Question->OptionListHead, Link)) {\r
3919 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
3920 Link = GetNextNode (&Question->OptionListHead, Link);\r
3921\r
3922 if ((Option->SuppressExpression != NULL) &&\r
3923 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
3924 continue;\r
3925 }\r
7936fb6a 3926\r
3927 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
3928 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
3929 ) {\r
3930 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
3931\r
3932 return EFI_SUCCESS;\r
3933 }\r
7936fb6a 3934 }\r
3935 }\r
3936 }\r
3937\r
3938 //\r
3939 // EFI_IFR_CHECKBOX - lowest priority\r
3940 //\r
3941 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
3942 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3943 //\r
3944 // Checkbox could only provide Standard and Manufacturing default\r
3945 //\r
3946 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
3947 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
3948 ) {\r
3949 HiiValue->Value.b = TRUE;\r
3950 } else {\r
3951 HiiValue->Value.b = FALSE;\r
3952 }\r
3953\r
3954 return EFI_SUCCESS;\r
3955 }\r
3956 }\r
3957\r
3958 //\r
3959 // For Questions without default\r
3960 //\r
48a9d5f7 3961 Status = EFI_NOT_FOUND;\r
7936fb6a 3962 switch (Question->Operand) {\r
cf4c5a42
LG
3963 case EFI_IFR_NUMERIC_OP:\r
3964 //\r
3965 // Take minimum value as numeric default value\r
3966 //\r
afc9bf79
ED
3967 if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {\r
3968 //\r
3969 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
3970 //\r
3971 switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {\r
3972 case EFI_IFR_NUMERIC_SIZE_1:\r
3973 if (((INT8) HiiValue->Value.u8 < (INT8) Question->Minimum) || ((INT8) HiiValue->Value.u8 > (INT8) Question->Maximum)) {\r
3974 HiiValue->Value.u8 = (UINT8) Question->Minimum;\r
3975 Status = EFI_SUCCESS;\r
3976 }\r
3977 break;\r
3978 case EFI_IFR_NUMERIC_SIZE_2:\r
3979 if (((INT16) HiiValue->Value.u16 < (INT16) Question->Minimum) || ((INT16) HiiValue->Value.u16 > (INT16) Question->Maximum)) {\r
3980 HiiValue->Value.u16 = (UINT16) Question->Minimum;\r
3981 Status = EFI_SUCCESS;\r
3982 }\r
3983 break;\r
3984 case EFI_IFR_NUMERIC_SIZE_4:\r
3985 if (((INT32) HiiValue->Value.u32 < (INT32) Question->Minimum) || ((INT32) HiiValue->Value.u32 > (INT32) Question->Maximum)) {\r
3986 HiiValue->Value.u32 = (UINT32) Question->Minimum;\r
3987 Status = EFI_SUCCESS;\r
3988 }\r
3989 break;\r
3990 case EFI_IFR_NUMERIC_SIZE_8:\r
3991 if (((INT64) HiiValue->Value.u64 < (INT64) Question->Minimum) || ((INT64) HiiValue->Value.u64 > (INT64) Question->Maximum)) {\r
3992 HiiValue->Value.u64 = Question->Minimum;\r
3993 Status = EFI_SUCCESS;\r
3994 }\r
3995 break;\r
3996 default:\r
3997 break; \r
3998 }\r
3999 } else {\r
4000 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
4001 HiiValue->Value.u64 = Question->Minimum;\r
4002 Status = EFI_SUCCESS;\r
4003 }\r
cf4c5a42
LG
4004 }\r
4005 break;\r
4006\r
7936fb6a 4007 case EFI_IFR_ONE_OF_OP:\r
4008 //\r
4009 // Take first oneof option as oneof's default value\r
4010 //\r
d66e6c16 4011 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed 4012 Link = GetFirstNode (&Question->OptionListHead);\r
82612023 4013 while (!IsNull (&Question->OptionListHead, Link)) {\r
0a1147ed 4014 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4015 Link = GetNextNode (&Question->OptionListHead, Link);\r
4016\r
4017 if ((Option->SuppressExpression != NULL) &&\r
4018 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4019 continue;\r
4020 }\r
4021\r
0a1147ed 4022 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 4023 Status = EFI_SUCCESS;\r
82612023 4024 break;\r
0a1147ed 4025 }\r
7936fb6a 4026 }\r
4027 break;\r
4028\r
4029 case EFI_IFR_ORDERED_LIST_OP:\r
4030 //\r
4031 // Take option sequence in IFR as ordered list's default value\r
4032 //\r
4033 Index = 0;\r
4034 Link = GetFirstNode (&Question->OptionListHead);\r
4035 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 4036 Status = EFI_SUCCESS;\r
7936fb6a 4037 Option = QUESTION_OPTION_FROM_LINK (Link);\r
82612023
ED
4038 Link = GetNextNode (&Question->OptionListHead, Link);\r
4039\r
4040 if ((Option->SuppressExpression != NULL) &&\r
4041 EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
4042 continue;\r
4043 }\r
7936fb6a 4044\r
d02847d3 4045 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 4046\r
4047 Index++;\r
4048 if (Index >= Question->MaxContainers) {\r
4049 break;\r
4050 }\r
7936fb6a 4051 }\r
4052 break;\r
4053\r
4054 default:\r
7936fb6a 4055 break;\r
4056 }\r
4057\r
4058 return Status;\r
4059}\r
4060\r
7a9612ce
ED
4061/**\r
4062 Get AltCfg string for current form.\r
4063\r
4064 @param FormSet Form data structure.\r
4065 @param Form Form data structure.\r
4066 @param DefaultId The Class of the default.\r
787fc2a6 4067 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4068\r
4069**/\r
4070VOID\r
4071ExtractAltCfgForForm (\r
4072 IN FORM_BROWSER_FORMSET *FormSet,\r
4073 IN FORM_BROWSER_FORM *Form,\r
787fc2a6
ED
4074 IN UINT16 DefaultId,\r
4075 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4076 )\r
4077{\r
4078 EFI_STATUS Status;\r
4079 LIST_ENTRY *Link;\r
4080 CHAR16 *ConfigResp;\r
4081 CHAR16 *Progress;\r
4082 CHAR16 *Result;\r
4083 BROWSER_STORAGE *Storage;\r
4084 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4085 FORMSET_STORAGE *FormSetStorage;\r
4086\r
4087 //\r
4088 // Check whether has get AltCfg string for this formset.\r
4089 // If yes, no need to get AltCfg for form.\r
4090 //\r
4091 Link = GetFirstNode (&FormSet->StorageListHead);\r
4092 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4093 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4094 Storage = FormSetStorage->BrowserStorage;\r
4095 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
787fc2a6
ED
4096 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4097 continue;\r
4098 }\r
7a9612ce
ED
4099\r
4100 if (Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE &&\r
4101 FormSetStorage->ElementCount != 0 &&\r
787fc2a6 4102 FormSetStorage->HasCallAltCfg) {\r
7a9612ce
ED
4103 return;\r
4104 }\r
4105 }\r
4106\r
4107 //\r
4108 // Get AltCfg string for each form.\r
4109 //\r
4110 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4111 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4112 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4113 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4114\r
4115 Storage = ConfigInfo->Storage;\r
787fc2a6
ED
4116 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4117 continue;\r
4118 }\r
4119\r
7a9612ce
ED
4120 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4121 continue;\r
4122 }\r
4123\r
4124 //\r
4125 // 1. Skip if there is no RequestElement\r
4126 //\r
4127 if (ConfigInfo->ElementCount == 0) {\r
4128 continue;\r
4129 }\r
4130\r
4131 //\r
4132 // 2. Get value through hii config routine protocol.\r
4133 //\r
4134 Status = mHiiConfigRouting->ExtractConfig (\r
4135 mHiiConfigRouting,\r
4136 ConfigInfo->ConfigRequest,\r
4137 &Progress,\r
4138 &Result\r
4139 );\r
4140 if (EFI_ERROR (Status)) {\r
4141 continue;\r
4142 }\r
4143\r
4144 //\r
4145 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4146 // Get the default configuration string according to the default ID.\r
4147 //\r
4148 Status = mHiiConfigRouting->GetAltConfig (\r
4149 mHiiConfigRouting,\r
4150 Result,\r
4151 &Storage->Guid,\r
4152 Storage->Name,\r
4153 NULL,\r
4154 &DefaultId, // it can be NULL to get the current setting.\r
4155 &ConfigResp\r
4156 );\r
4157 FreePool (Result);\r
4158 if (EFI_ERROR (Status)) {\r
4159 continue;\r
4160 }\r
4161\r
4162 ConfigInfo->ConfigAltResp = ConfigResp;\r
4163 }\r
4164}\r
4165\r
4166/**\r
4167 Clean AltCfg string for current form.\r
4168\r
4169 @param Form Form data structure.\r
4170\r
4171**/\r
4172VOID\r
4173CleanAltCfgForForm (\r
4174 IN FORM_BROWSER_FORM *Form\r
4175 )\r
4176{\r
4177 LIST_ENTRY *Link;\r
4178 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
4179\r
4180 Link = GetFirstNode (&Form->ConfigRequestHead);\r
4181 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
4182 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
4183 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
4184\r
4185 if (ConfigInfo->ConfigAltResp != NULL) {\r
4186 FreePool (ConfigInfo->ConfigAltResp);\r
4187 ConfigInfo->ConfigAltResp = NULL;\r
4188 }\r
4189 }\r
4190}\r
4191\r
4192/**\r
4193 Get AltCfg string for current formset.\r
4194\r
4195 @param FormSet Form data structure.\r
4196 @param DefaultId The Class of the default.\r
787fc2a6 4197 @param BrowserStorage The input request storage for the questions.\r
7a9612ce
ED
4198\r
4199**/\r
4200VOID\r
4201ExtractAltCfgForFormSet (\r
4202 IN FORM_BROWSER_FORMSET *FormSet,\r
787fc2a6
ED
4203 IN UINT16 DefaultId,\r
4204 IN BROWSER_STORAGE *BrowserStorage\r
7a9612ce
ED
4205 )\r
4206{\r
4207 EFI_STATUS Status;\r
4208 LIST_ENTRY *Link;\r
4209 CHAR16 *ConfigResp;\r
4210 CHAR16 *Progress;\r
4211 CHAR16 *Result;\r
4212 BROWSER_STORAGE *Storage;\r
4213 FORMSET_STORAGE *FormSetStorage;\r
4214\r
4215 Link = GetFirstNode (&FormSet->StorageListHead);\r
4216 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4217 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4218 Storage = FormSetStorage->BrowserStorage;\r
4219 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4220\r
787fc2a6
ED
4221 if (BrowserStorage != NULL && BrowserStorage != Storage) {\r
4222 continue;\r
4223 }\r
4224\r
7a9612ce
ED
4225 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
4226 continue;\r
4227 }\r
4228\r
4229 //\r
4230 // 1. Skip if there is no RequestElement\r
4231 //\r
4232 if (FormSetStorage->ElementCount == 0) {\r
4233 continue;\r
4234 }\r
4235\r
787fc2a6
ED
4236 FormSetStorage->HasCallAltCfg = TRUE;\r
4237\r
7a9612ce
ED
4238 //\r
4239 // 2. Get value through hii config routine protocol.\r
4240 //\r
4241 Status = mHiiConfigRouting->ExtractConfig (\r
4242 mHiiConfigRouting,\r
4243 FormSetStorage->ConfigRequest,\r
4244 &Progress,\r
4245 &Result\r
4246 );\r
4247 if (EFI_ERROR (Status)) {\r
4248 continue;\r
4249 }\r
4250\r
4251 //\r
4252 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
4253 // Get the default configuration string according to the default ID.\r
4254 //\r
4255 Status = mHiiConfigRouting->GetAltConfig (\r
4256 mHiiConfigRouting,\r
4257 Result,\r
4258 &Storage->Guid,\r
4259 Storage->Name,\r
4260 NULL,\r
4261 &DefaultId, // it can be NULL to get the current setting.\r
4262 &ConfigResp\r
4263 );\r
4264\r
4265 FreePool (Result);\r
4266 if (EFI_ERROR (Status)) {\r
4267 continue;\r
4268 }\r
4269\r
4270 FormSetStorage->ConfigAltResp = ConfigResp;\r
4271 }\r
4272\r
4273}\r
4274\r
4275/**\r
4276 Clean AltCfg string for current formset.\r
4277\r
4278 @param FormSet Form data structure.\r
4279\r
4280**/\r
4281VOID\r
4282CleanAltCfgForFormSet (\r
4283 IN FORM_BROWSER_FORMSET *FormSet\r
4284 )\r
4285{\r
4286 LIST_ENTRY *Link;\r
4287 FORMSET_STORAGE *FormSetStorage;\r
4288\r
4289 Link = GetFirstNode (&FormSet->StorageListHead);\r
4290 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4291 FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
4292 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4293\r
4294 if (FormSetStorage->ConfigAltResp != NULL) {\r
4295 FreePool (FormSetStorage->ConfigAltResp);\r
4296 FormSetStorage->ConfigAltResp = NULL;\r
4297 }\r
787fc2a6
ED
4298\r
4299 FormSetStorage->HasCallAltCfg = FALSE;\r
7a9612ce
ED
4300 }\r
4301}\r
7936fb6a 4302\r
4303/**\r
9776099f 4304 Reset Questions to their initial value or default value in a Form, Formset or System.\r
7936fb6a 4305\r
09cdd7d2
ED
4306 GetDefaultValueScope parameter decides which questions will reset \r
4307 to its default value.\r
4308\r
7936fb6a 4309 @param FormSet FormSet data structure.\r
48a9d5f7 4310 @param Form Form data structure.\r
7936fb6a 4311 @param DefaultId The Class of the default.\r
48a9d5f7 4312 @param SettingScope Setting Scope for Default action.\r
09cdd7d2 4313 @param GetDefaultValueScope Get default value scope.\r
3347d410 4314 @param Storage Get default value only for this storage.\r
9776099f
ED
4315 @param RetrieveValueFirst Whether call the retrieve call back to\r
4316 get the initial value before get default\r
4317 value.\r
787fc2a6 4318 @param SkipGetAltCfg Whether skip the get altcfg string process.\r
7936fb6a 4319\r
4320 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 4321 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 4322\r
4323**/\r
4324EFI_STATUS\r
48a9d5f7 4325ExtractDefault (\r
7936fb6a 4326 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
4327 IN FORM_BROWSER_FORM *Form,\r
4328 IN UINT16 DefaultId,\r
3347d410 4329 IN BROWSER_SETTING_SCOPE SettingScope,\r
09cdd7d2 4330 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
94f3aae7 4331 IN BROWSER_STORAGE *Storage OPTIONAL,\r
787fc2a6
ED
4332 IN BOOLEAN RetrieveValueFirst,\r
4333 IN BOOLEAN SkipGetAltCfg\r
7936fb6a 4334 )\r
4335{\r
4336 EFI_STATUS Status;\r
4f33c838 4337 LIST_ENTRY *FormLink;\r
48a9d5f7 4338 LIST_ENTRY *Link;\r
7936fb6a 4339 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7 4340 FORM_BROWSER_FORMSET *LocalFormSet;\r
6e74560f 4341 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 4342\r
9776099f
ED
4343 Status = EFI_SUCCESS;\r
4344\r
48a9d5f7
LG
4345 //\r
4346 // Check the supported setting level.\r
4347 //\r
09cdd7d2
ED
4348 if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
4349 return EFI_UNSUPPORTED;\r
4350 }\r
4351\r
4352 if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
48a9d5f7
LG
4353 return EFI_UNSUPPORTED;\r
4354 }\r
7a9612ce 4355\r
48a9d5f7 4356 if (SettingScope == FormLevel) {\r
7a9612ce
ED
4357 //\r
4358 // Prepare the AltCfg String for form.\r
4359 //\r
787fc2a6
ED
4360 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4361 ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
4362 }\r
7a9612ce 4363\r
8d00a0f1 4364 //\r
4f33c838 4365 // Extract Form default\r
8d00a0f1 4366 //\r
48a9d5f7
LG
4367 Link = GetFirstNode (&Form->StatementListHead);\r
4368 while (!IsNull (&Form->StatementListHead, Link)) {\r
4369 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4370 Link = GetNextNode (&Form->StatementListHead, Link);\r
3347d410
ED
4371\r
4372 //\r
4373 // If get default value only for this storage, check the storage first.\r
4374 //\r
09cdd7d2
ED
4375 if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
4376 continue;\r
4377 }\r
4378\r
4379 //\r
4380 // If get default value only for no storage question, just skip the question which has storage.\r
4381 //\r
4382 if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
3347d410
ED
4383 continue;\r
4384 }\r
4385\r
4f33c838
ED
4386 //\r
4387 // If Question is disabled, don't reset it to default\r
4388 //\r
31585af4
ED
4389 if (Question->Expression != NULL) {\r
4390 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
4391 continue;\r
4392 }\r
8d00a0f1 4393 }\r
9776099f
ED
4394\r
4395 if (RetrieveValueFirst) {\r
4396 //\r
4397 // Call the Retrieve call back to get the initial question value.\r
4398 //\r
061d5462 4399 Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);\r
9776099f
ED
4400 }\r
4401\r
4f33c838 4402 //\r
9776099f 4403 // If not request to get the initial value or get initial value fail, then get default value.\r
4f33c838 4404 //\r
9776099f
ED
4405 if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
4406 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
4407 if (EFI_ERROR (Status)) {\r
4408 continue;\r
4409 }\r
4f33c838 4410 }\r
9776099f 4411\r
4f33c838
ED
4412 //\r
4413 // Synchronize Buffer storage's Edit buffer\r
4414 //\r
4415 if ((Question->Storage != NULL) &&\r
4416 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
816a7110 4417 SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
48a9d5f7
LG
4418 }\r
4419 }\r
7a9612ce
ED
4420\r
4421 //\r
4422 // Clean the AltCfg String.\r
4423 //\r
787fc2a6
ED
4424 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4425 CleanAltCfgForForm(Form);\r
4426 }\r
48a9d5f7 4427 } else if (SettingScope == FormSetLevel) {\r
7a9612ce
ED
4428 //\r
4429 // Prepare the AltCfg String for formset.\r
4430 //\r
787fc2a6
ED
4431 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4432 ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
4433 }\r
7a9612ce 4434\r
48a9d5f7
LG
4435 FormLink = GetFirstNode (&FormSet->FormListHead);\r
4436 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
4437 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
787fc2a6 4438 ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
48a9d5f7
LG
4439 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
4440 }\r
7a9612ce
ED
4441\r
4442 //\r
4443 // Clean the AltCfg String.\r
4444 //\r
787fc2a6
ED
4445 if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
4446 CleanAltCfgForFormSet (FormSet);\r
4447 }\r
48a9d5f7
LG
4448 } else if (SettingScope == SystemLevel) {\r
4449 //\r
7c6c064c 4450 // Preload all Hii formset.\r
48a9d5f7 4451 //\r
7c6c064c 4452 LoadAllHiiFormset();\r
6e74560f
ED
4453\r
4454 OldFormSet = mSystemLevelFormSet;\r
4455\r
48a9d5f7
LG
4456 //\r
4457 // Set Default Value for each FormSet in the maintain list.\r
4458 //\r
4459 Link = GetFirstNode (&gBrowserFormSetList);\r
4460 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4461 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
48a9d5f7 4462 Link = GetNextNode (&gBrowserFormSetList, Link);\r
938baa1f
ED
4463 if (!ValidateFormSet(LocalFormSet)) {\r
4464 continue;\r
4465 }\r
6e74560f
ED
4466\r
4467 mSystemLevelFormSet = LocalFormSet;\r
4468\r
787fc2a6 4469 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
7936fb6a 4470 }\r
6e74560f
ED
4471\r
4472 mSystemLevelFormSet = OldFormSet;\r
7936fb6a 4473 }\r
4474\r
4475 return EFI_SUCCESS;\r
4476}\r
4477\r
7c6c064c
ED
4478\r
4479/**\r
4480 Validate whether this question's value has changed.\r
4481\r
4482 @param FormSet FormSet data structure.\r
4483 @param Form Form data structure.\r
4484 @param Question Question to be initialized.\r
4485 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
4486\r
4487 @retval TRUE Question's value has changed.\r
4488 @retval FALSE Question's value has not changed\r
4489\r
4490**/\r
4491BOOLEAN\r
4492IsQuestionValueChanged (\r
4493 IN FORM_BROWSER_FORMSET *FormSet,\r
4494 IN FORM_BROWSER_FORM *Form,\r
4495 IN OUT FORM_BROWSER_STATEMENT *Question,\r
4496 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
4497 )\r
4498{\r
4499 EFI_HII_VALUE BackUpValue;\r
4500 CHAR8 *BackUpBuffer;\r
4d4deaac
ED
4501 EFI_HII_VALUE BackUpValue2;\r
4502 CHAR8 *BackUpBuffer2;\r
7c6c064c
ED
4503 EFI_STATUS Status;\r
4504 BOOLEAN ValueChanged;\r
4505 UINTN BufferWidth;\r
4506\r
4507 //\r
4508 // For quetion without storage, always mark it as data not changed.\r
4509 //\r
4510 if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
4511 return FALSE;\r
4512 }\r
4513\r
4514 BackUpBuffer = NULL;\r
4d4deaac 4515 BackUpBuffer2 = NULL;\r
7c6c064c
ED
4516 ValueChanged = FALSE;\r
4517\r
4518 switch (Question->Operand) {\r
4519 case EFI_IFR_ORDERED_LIST_OP:\r
4520 BufferWidth = Question->StorageWidth;\r
4521 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4522 ASSERT (BackUpBuffer != NULL);\r
4523 break;\r
4524\r
4525 case EFI_IFR_STRING_OP:\r
4526 case EFI_IFR_PASSWORD_OP:\r
4527 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4528 BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4529 ASSERT (BackUpBuffer != NULL);\r
4530 break;\r
4531\r
4532 default:\r
4533 BufferWidth = 0;\r
4534 break;\r
4535 }\r
4536 CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4537\r
4d4deaac
ED
4538 if (GetValueFrom == GetSetValueWithBothBuffer) {\r
4539 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4540 ASSERT_EFI_ERROR(Status);\r
7c6c064c 4541\r
4d4deaac
ED
4542 switch (Question->Operand) {\r
4543 case EFI_IFR_ORDERED_LIST_OP:\r
4544 BufferWidth = Question->StorageWidth;\r
4545 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4546 ASSERT (BackUpBuffer2 != NULL);\r
4547 break;\r
4548\r
4549 case EFI_IFR_STRING_OP:\r
4550 case EFI_IFR_PASSWORD_OP:\r
4551 BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
4552 BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
4553 ASSERT (BackUpBuffer2 != NULL);\r
4554 break;\r
4555\r
4556 default:\r
4557 BufferWidth = 0;\r
4558 break;\r
4559 }\r
4560 CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
4561\r
4562 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
4563 ASSERT_EFI_ERROR(Status);\r
4564\r
4565 if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4566 CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
4567 ValueChanged = TRUE;\r
4568 }\r
4569 } else {\r
4570 Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
4571 ASSERT_EFI_ERROR(Status);\r
4572\r
4573 if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
4574 CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
4575 ValueChanged = TRUE;\r
4576 }\r
7c6c064c
ED
4577 }\r
4578\r
4579 CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
7c6c064c 4580 if (BackUpBuffer != NULL) {\r
e77d2f9d 4581 CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
7c6c064c
ED
4582 FreePool (BackUpBuffer);\r
4583 }\r
4584\r
4d4deaac
ED
4585 if (BackUpBuffer2 != NULL) {\r
4586 FreePool (BackUpBuffer2);\r
4587 }\r
4588\r
892eccc8
ED
4589 Question->ValueChanged = ValueChanged;\r
4590\r
7c6c064c
ED
4591 return ValueChanged;\r
4592}\r
4593\r
7936fb6a 4594/**\r
4595 Initialize Question's Edit copy from Storage.\r
4596\r
eccfeab1
LG
4597 @param Selection Selection contains the information about \r
4598 the Selection, form and formset to be displayed.\r
4599 Selection action may be updated in retrieve callback.\r
7d1b202d 4600 If Selection is NULL, only initialize Question value.\r
7936fb6a 4601 @param FormSet FormSet data structure.\r
4602 @param Form Form data structure.\r
4603\r
4604 @retval EFI_SUCCESS The function completed successfully.\r
4605\r
4606**/\r
4607EFI_STATUS\r
4608LoadFormConfig (\r
eccfeab1
LG
4609 IN OUT UI_MENU_SELECTION *Selection,\r
4610 IN FORM_BROWSER_FORMSET *FormSet,\r
4611 IN FORM_BROWSER_FORM *Form\r
7936fb6a 4612 )\r
4613{\r
eccfeab1
LG
4614 EFI_STATUS Status;\r
4615 LIST_ENTRY *Link;\r
4616 FORM_BROWSER_STATEMENT *Question;\r
eccfeab1 4617 \r
7936fb6a 4618 Link = GetFirstNode (&Form->StatementListHead);\r
4619 while (!IsNull (&Form->StatementListHead, Link)) {\r
4620 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
4621\r
4622 //\r
4623 // Initialize local copy of Value for each Question\r
4624 //\r
7c6c064c
ED
4625 if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
4626 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
4627 } else {\r
4628 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
4629 }\r
7936fb6a 4630 if (EFI_ERROR (Status)) {\r
4631 return Status;\r
4632 }\r
e2100bfa
ED
4633\r
4634 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
4635 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
4636 }\r
4637\r
7936fb6a 4638 Link = GetNextNode (&Form->StatementListHead, Link);\r
4639 }\r
4640\r
4641 return EFI_SUCCESS;\r
4642}\r
4643\r
d66e6c16 4644/**\r
4645 Initialize Question's Edit copy from Storage for the whole Formset.\r
4646\r
eccfeab1
LG
4647 @param Selection Selection contains the information about \r
4648 the Selection, form and formset to be displayed.\r
4649 Selection action may be updated in retrieve callback.\r
7d1b202d 4650 If Selection is NULL, only initialize Question value.\r
d66e6c16 4651 @param FormSet FormSet data structure.\r
4652\r
4653 @retval EFI_SUCCESS The function completed successfully.\r
4654\r
4655**/\r
4656EFI_STATUS\r
4657LoadFormSetConfig (\r
eccfeab1
LG
4658 IN OUT UI_MENU_SELECTION *Selection,\r
4659 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 4660 )\r
4661{\r
eccfeab1
LG
4662 EFI_STATUS Status;\r
4663 LIST_ENTRY *Link;\r
4664 FORM_BROWSER_FORM *Form;\r
d66e6c16 4665\r
4666 Link = GetFirstNode (&FormSet->FormListHead);\r
4667 while (!IsNull (&FormSet->FormListHead, Link)) {\r
4668 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
4669\r
4670 //\r
4671 // Initialize local copy of Value for each Form\r
4672 //\r
eccfeab1 4673 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 4674 if (EFI_ERROR (Status)) {\r
4675 return Status;\r
4676 }\r
4677\r
4678 Link = GetNextNode (&FormSet->FormListHead, Link);\r
4679 }\r
4680\r
7c6c064c
ED
4681 //\r
4682 // Finished question initialization.\r
4683 // \r
4684 FormSet->QuestionInited = TRUE;\r
4685\r
d66e6c16 4686 return EFI_SUCCESS;\r
4687}\r
4688\r
0a6f8af5
ED
4689/**\r
4690 Remove the Request element from the Config Request.\r
4691\r
4692 @param Storage Pointer to the browser storage.\r
4693 @param RequestElement The pointer to the Request element.\r
4694\r
4695**/\r
4696VOID\r
4697RemoveElement (\r
4698 IN OUT BROWSER_STORAGE *Storage,\r
4699 IN CHAR16 *RequestElement\r
4700 )\r
4701{\r
4702 CHAR16 *NewStr;\r
4703 CHAR16 *DestStr;\r
4704\r
4705 ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
4706\r
4707 NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
4708\r
4709 if (NewStr == NULL) {\r
4710 return;\r
4711 }\r
4712\r
4713 //\r
4714 // Remove this element from this ConfigRequest.\r
4715 //\r
4716 DestStr = NewStr;\r
4717 NewStr += StrLen (RequestElement);\r
4718 CopyMem (DestStr, NewStr, StrSize (NewStr));\r
4719 \r
4720 Storage->SpareStrLen += StrLen (RequestElement); \r
4721}\r
4722\r
4723/**\r
4724 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
4725\r
a35ecb75 4726 @param Storage Pointer to the formset storage.\r
0a6f8af5
ED
4727 @param ConfigRequest The pointer to the Request element.\r
4728\r
4729**/\r
4730VOID\r
4731RemoveConfigRequest (\r
a35ecb75 4732 FORMSET_STORAGE *Storage,\r
0a6f8af5
ED
4733 CHAR16 *ConfigRequest\r
4734 )\r
4735{\r
4736 CHAR16 *RequestElement;\r
4737 CHAR16 *NextRequestElement;\r
4738 CHAR16 *SearchKey;\r
4739\r
7c6c064c
ED
4740 //\r
4741 // No request element in it, just return.\r
4742 //\r
4743 if (ConfigRequest == NULL) {\r
4744 return;\r
4745 }\r
4746\r
a35ecb75 4747 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
4748 //\r
4749 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4750 //\r
4751 SearchKey = L"&";\r
4752 } else {\r
4753 //\r
4754 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4755 //\r
4756 SearchKey = L"&OFFSET";\r
4757 }\r
4758\r
4759 //\r
4760 // Find SearchKey storage\r
4761 //\r
a35ecb75 4762 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
0a6f8af5
ED
4763 RequestElement = StrStr (ConfigRequest, L"PATH");\r
4764 ASSERT (RequestElement != NULL);\r
4765 RequestElement = StrStr (RequestElement, SearchKey); \r
4766 } else {\r
4767 RequestElement = StrStr (ConfigRequest, SearchKey);\r
4768 }\r
4769\r
4770 while (RequestElement != NULL) {\r
4771 //\r
4772 // +1 to avoid find header itself.\r
4773 //\r
4774 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4775\r
4776 //\r
4777 // The last Request element in configRequest string.\r
4778 //\r
4779 if (NextRequestElement != NULL) {\r
4780 //\r
4781 // Replace "&" with '\0'.\r
4782 //\r
4783 *NextRequestElement = L'\0';\r
4784 }\r
4785\r
a35ecb75 4786 RemoveElement (Storage->BrowserStorage, RequestElement);\r
0a6f8af5
ED
4787\r
4788 if (NextRequestElement != NULL) {\r
4789 //\r
4790 // Restore '&' with '\0' for later used.\r
4791 //\r
4792 *NextRequestElement = L'&';\r
4793 }\r
4794\r
4795 RequestElement = NextRequestElement;\r
4796 }\r
4797\r
4798 //\r
4799 // If no request element remain, just remove the ConfigRequest string.\r
4800 //\r
a35ecb75
ED
4801 if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
4802 FreePool (Storage->BrowserStorage->ConfigRequest);\r
4803 Storage->BrowserStorage->ConfigRequest = NULL;\r
4804 Storage->BrowserStorage->SpareStrLen = 0;\r
0a6f8af5
ED
4805 }\r
4806}\r
4807\r
4808/**\r
4809 Base on the current formset info, clean the ConfigRequest string in browser storage.\r
4810\r
4811 @param FormSet Pointer of the FormSet\r
4812\r
4813**/\r
4814VOID\r
4815CleanBrowserStorage (\r
4816 IN OUT FORM_BROWSER_FORMSET *FormSet\r
4817 )\r
4818{\r
4819 LIST_ENTRY *Link;\r
4820 FORMSET_STORAGE *Storage;\r
4821\r
4822 Link = GetFirstNode (&FormSet->StorageListHead);\r
4823 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
4824 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
4825 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
4826\r
fae73624
ED
4827 if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
4828 if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
4829 continue;\r
4830 }\r
0a6f8af5 4831\r
a35ecb75 4832 RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
fae73624
ED
4833 } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
4834 Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4835 if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
4836 FreePool (Storage->BrowserStorage->ConfigRequest);\r
5dc6ab16 4837 Storage->BrowserStorage->ConfigRequest = NULL;\r
fae73624
ED
4838 }\r
4839 Storage->BrowserStorage->Initialized = FALSE;\r
0a6f8af5 4840 }\r
0a6f8af5
ED
4841 }\r
4842}\r
4843\r
efffd9c1
ED
4844/**\r
4845 Check whether current element in the ConfigReqeust string.\r
4846\r
4847 @param BrowserStorage Storage which includes ConfigReqeust.\r
4848 @param RequestElement New element need to check.\r
4849\r
4850 @retval TRUE The Element is in the ConfigReqeust string.\r
4851 @retval FALSE The Element not in the configReqeust String.\r
4852\r
4853**/\r
4854BOOLEAN \r
4855ElementValidation (\r
4856 BROWSER_STORAGE *BrowserStorage,\r
4857 CHAR16 *RequestElement\r
4858 )\r
4859{\r
4860 return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
4861}\r
4862\r
4863/**\r
4864 Append the Request element to the Config Request.\r
4865\r
4866 @param ConfigRequest Current ConfigRequest info.\r
4867 @param SpareStrLen Current remain free buffer for config reqeust.\r
4868 @param RequestElement New Request element.\r
4869\r
4870**/\r
4871VOID\r
4872AppendConfigRequest (\r
4873 IN OUT CHAR16 **ConfigRequest,\r
4874 IN OUT UINTN *SpareStrLen,\r
4875 IN CHAR16 *RequestElement\r
4876 )\r
4877{\r
4878 CHAR16 *NewStr;\r
4879 UINTN StringSize;\r
4880 UINTN StrLength;\r
4881\r
0a6f8af5 4882 StrLength = StrLen (RequestElement);\r
efffd9c1
ED
4883\r
4884 //\r
4885 // Append <RequestElement> to <ConfigRequest>\r
4886 //\r
4887 if (StrLength > *SpareStrLen) {\r
4888 //\r
4889 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
4890 //\r
4891 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
4892 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
4893 ASSERT (NewStr != NULL);\r
4894\r
4895 if (*ConfigRequest != NULL) {\r
4896 CopyMem (NewStr, *ConfigRequest, StringSize);\r
4897 FreePool (*ConfigRequest);\r
4898 }\r
4899 *ConfigRequest = NewStr;\r
4900 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
4901 }\r
4902\r
4903 StrCat (*ConfigRequest, RequestElement);\r
4904 *SpareStrLen -= StrLength;\r
4905}\r
4906\r
4907/**\r
4908 Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
4909\r
4910 @param Storage Form set Storage.\r
9d34cac8
ED
4911 @param Request The input request string.\r
4912 @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
efffd9c1
ED
4913\r
4914 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
4915 @retval FALSE All elements covered by current used elements.\r
4916\r
4917**/\r
4918BOOLEAN \r
4919ConfigRequestAdjust (\r
9d34cac8
ED
4920 IN BROWSER_STORAGE *Storage,\r
4921 IN CHAR16 *Request,\r
4922 IN BOOLEAN RespString\r
efffd9c1
ED
4923 )\r
4924{\r
4925 CHAR16 *RequestElement;\r
4926 CHAR16 *NextRequestElement;\r
9d34cac8 4927 CHAR16 *NextElementBakup;\r
efffd9c1 4928 CHAR16 *SearchKey;\r
9d34cac8 4929 CHAR16 *ValueKey;\r
efffd9c1 4930 BOOLEAN RetVal;\r
9d34cac8 4931 CHAR16 *ConfigRequest;\r
efffd9c1 4932\r
efffd9c1 4933 RetVal = FALSE;\r
9d34cac8
ED
4934 NextElementBakup = NULL;\r
4935 ValueKey = NULL;\r
efffd9c1 4936\r
9d34cac8
ED
4937 if (Request != NULL) {\r
4938 ConfigRequest = Request;\r
4939 } else {\r
4940 ConfigRequest = Storage->ConfigRequest;\r
4941 }\r
4942\r
4943 if (Storage->ConfigRequest == NULL) {\r
4944 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
efffd9c1
ED
4945 return TRUE;\r
4946 }\r
4947\r
9d34cac8 4948 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
efffd9c1
ED
4949 //\r
4950 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
4951 //\r
4952 SearchKey = L"&";\r
4953 } else {\r
4954 //\r
4955 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
4956 //\r
4957 SearchKey = L"&OFFSET";\r
9d34cac8 4958 ValueKey = L"&VALUE";\r
efffd9c1
ED
4959 }\r
4960\r
efffd9c1
ED
4961 //\r
4962 // Find SearchKey storage\r
4963 //\r
9d34cac8
ED
4964 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4965 RequestElement = StrStr (ConfigRequest, L"PATH");\r
efffd9c1
ED
4966 ASSERT (RequestElement != NULL);\r
4967 RequestElement = StrStr (RequestElement, SearchKey); \r
4968 } else {\r
9d34cac8 4969 RequestElement = StrStr (ConfigRequest, SearchKey);\r
efffd9c1
ED
4970 }\r
4971\r
4972 while (RequestElement != NULL) {\r
9d34cac8 4973\r
efffd9c1
ED
4974 //\r
4975 // +1 to avoid find header itself.\r
4976 //\r
4977 NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
4978\r
4979 //\r
4980 // The last Request element in configRequest string.\r
4981 //\r
4982 if (NextRequestElement != NULL) {\r
9d34cac8
ED
4983 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4984 NextElementBakup = NextRequestElement;\r
4985 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 4986 ASSERT (NextRequestElement != NULL);\r
9d34cac8 4987 }\r
efffd9c1
ED
4988 //\r
4989 // Replace "&" with '\0'.\r
4990 //\r
4991 *NextRequestElement = L'\0';\r
9d34cac8
ED
4992 } else {\r
4993 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
4994 NextElementBakup = NextRequestElement;\r
4995 NextRequestElement = StrStr (RequestElement, ValueKey);\r
d8adff44 4996 ASSERT (NextRequestElement != NULL);\r
9d34cac8
ED
4997 //\r
4998 // Replace "&" with '\0'.\r
4999 //\r
5000 *NextRequestElement = L'\0';\r
5001 }\r
efffd9c1
ED
5002 }\r
5003 \r
9d34cac8 5004 if (!ElementValidation (Storage, RequestElement)) {\r
efffd9c1
ED
5005 //\r
5006 // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
5007 //\r
9d34cac8 5008 AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
efffd9c1
ED
5009 RetVal = TRUE;\r
5010 }\r
5011\r
5012 if (NextRequestElement != NULL) {\r
5013 //\r
5014 // Restore '&' with '\0' for later used.\r
5015 //\r
5016 *NextRequestElement = L'&';\r
5017 }\r
5018\r
9d34cac8
ED
5019 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
5020 RequestElement = NextElementBakup;\r
5021 } else {\r
5022 RequestElement = NextRequestElement;\r
7c6c064c 5023 }\r
efffd9c1
ED
5024 }\r
5025\r
5026 return RetVal;\r
5027}\r
5028\r
7936fb6a 5029/**\r
5030 Fill storage's edit copy with settings requested from Configuration Driver.\r
5031\r
5032 @param FormSet FormSet data structure.\r
5033 @param Storage Buffer Storage.\r
5034\r
7936fb6a 5035**/\r
7c6c064c 5036VOID\r
7936fb6a 5037LoadStorage (\r
5038 IN FORM_BROWSER_FORMSET *FormSet,\r
5039 IN FORMSET_STORAGE *Storage\r
5040 )\r
5041{\r
5042 EFI_STATUS Status;\r
5043 EFI_STRING Progress;\r
5044 EFI_STRING Result;\r
5045 CHAR16 *StrPtr;\r
98c4caa1
ED
5046 EFI_STRING ConfigRequest;\r
5047 UINTN StrLen;\r
5048\r
5049 ConfigRequest = NULL;\r
7936fb6a 5050\r
7c6c064c
ED
5051 switch (Storage->BrowserStorage->Type) {\r
5052 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
5053 return;\r
5054\r
5055 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
6e74560f 5056 if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
9d34cac8 5057 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
7c6c064c
ED
5058 return;\r
5059 }\r
7c6c064c 5060 break;\r
cce6230f 5061\r
7c6c064c
ED
5062 case EFI_HII_VARSTORE_BUFFER:\r
5063 case EFI_HII_VARSTORE_NAME_VALUE:\r
5064 //\r
27c304f4 5065 // Skip if there is no RequestElement.\r
7c6c064c 5066 //\r
27c304f4 5067 if (Storage->ElementCount == 0) {\r
7c6c064c
ED
5068 return;\r
5069 }\r
27c304f4
ED
5070\r
5071 //\r
5072 // Just update the ConfigRequest, if storage already initialized. \r
5073 //\r
5074 if (Storage->BrowserStorage->Initialized) {\r
9d34cac8 5075 ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
27c304f4
ED
5076 return;\r
5077 }\r
5078\r
fae73624 5079 Storage->BrowserStorage->Initialized = TRUE;\r
7c6c064c 5080 break;\r
7936fb6a 5081\r
7c6c064c 5082 default:\r
7248790e 5083 return;\r
7936fb6a 5084 }\r
7248790e 5085\r
27c304f4
ED
5086 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
5087 //\r
5088 // Create the config request string to get all fields for this storage.\r
5089 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
5090 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
5091 //\r
a35ecb75 5092 StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
27c304f4
ED
5093 ConfigRequest = AllocateZeroPool (StrLen);\r
5094 ASSERT (ConfigRequest != NULL);\r
5095 UnicodeSPrint (\r
5096 ConfigRequest, \r
5097 StrLen, \r
5098 L"%s&OFFSET=0&WIDTH=%04x", \r
a35ecb75 5099 Storage->ConfigHdr,\r
27c304f4
ED
5100 Storage->BrowserStorage->Size);\r
5101 } else {\r
5102 ConfigRequest = Storage->ConfigRequest;\r
5103 }\r
5104\r
7248790e
ED
5105 //\r
5106 // Request current settings from Configuration Driver\r
5107 //\r
5108 Status = mHiiConfigRouting->ExtractConfig (\r
5109 mHiiConfigRouting,\r
98c4caa1 5110 ConfigRequest,\r
7248790e
ED
5111 &Progress,\r
5112 &Result\r
5113 );\r
5114\r
5115 //\r
5116 // If get value fail, extract default from IFR binary\r
5117 //\r
5118 if (EFI_ERROR (Status)) {\r
787fc2a6 5119 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
7248790e
ED
5120 } else {\r
5121 //\r
5122 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
5123 //\r
5124 StrPtr = StrStr (Result, L"&GUID=");\r
5125 if (StrPtr != NULL) {\r
5126 *StrPtr = L'\0';\r
5127 }\r
5128 \r
5129 Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
5130 FreePool (Result);\r
5131 }\r
5132\r
5133 Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
5134\r
5135 //\r
5136 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
5137 //\r
4d4deaac 5138 SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
98c4caa1 5139\r
27c304f4 5140 if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
98c4caa1
ED
5141 if (ConfigRequest != NULL) {\r
5142 FreePool (ConfigRequest);\r
5143 }\r
5144 }\r
7936fb6a 5145}\r
5146\r
892eccc8
ED
5147/**\r
5148 Get Value changed status from old question.\r
5149\r
5150 @param NewFormSet FormSet data structure.\r
5151 @param OldQuestion Old question which has value changed.\r
5152\r
5153**/\r
5154VOID\r
5155SyncStatusForQuestion (\r
5156 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5157 IN FORM_BROWSER_STATEMENT *OldQuestion\r
5158 )\r
5159{\r
5160 LIST_ENTRY *Link;\r
5161 LIST_ENTRY *QuestionLink;\r
5162 FORM_BROWSER_FORM *Form;\r
5163 FORM_BROWSER_STATEMENT *Question;\r
5164\r
5165 //\r
5166 // For each form in one formset.\r
5167 //\r
5168 Link = GetFirstNode (&NewFormSet->FormListHead);\r
5169 while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
5170 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5171 Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
5172\r
5173 //\r
5174 // for each question in one form.\r
5175 //\r
5176 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5177 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5178 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5179 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5180\r
5181 if (Question->QuestionId == OldQuestion->QuestionId) {\r
5182 Question->ValueChanged = TRUE;\r
5183 return;\r
5184 }\r
5185 }\r
5186 }\r
5187}\r
5188\r
5189/**\r
5190 Get Value changed status from old formset.\r
5191\r
5192 @param NewFormSet FormSet data structure.\r
5193 @param OldFormSet FormSet data structure.\r
5194\r
5195**/\r
5196VOID\r
5197SyncStatusForFormSet (\r
5198 IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
5199 IN FORM_BROWSER_FORMSET *OldFormSet\r
5200 )\r
5201{\r
5202 LIST_ENTRY *Link;\r
5203 LIST_ENTRY *QuestionLink;\r
5204 FORM_BROWSER_FORM *Form;\r
5205 FORM_BROWSER_STATEMENT *Question;\r
5206\r
5207 //\r
5208 // For each form in one formset.\r
5209 //\r
5210 Link = GetFirstNode (&OldFormSet->FormListHead);\r
5211 while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
5212 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
5213 Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
5214\r
5215 //\r
5216 // for each question in one form.\r
5217 //\r
5218 QuestionLink = GetFirstNode (&Form->StatementListHead);\r
5219 while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
5220 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
5221 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
5222\r
5223 if (!Question->ValueChanged) {\r
5224 continue;\r
5225 }\r
5226\r
5227 //\r
5228 // Find the same question in new formset and update the value changed flag.\r
5229 //\r
5230 SyncStatusForQuestion (NewFormSet, Question);\r
5231 }\r
5232 }\r
5233}\r
5234\r
7936fb6a 5235/**\r
5236 Get current setting of Questions.\r
5237\r
5238 @param FormSet FormSet data structure.\r
5239\r
7936fb6a 5240**/\r
7c6c064c 5241VOID\r
7936fb6a 5242InitializeCurrentSetting (\r
5243 IN OUT FORM_BROWSER_FORMSET *FormSet\r
5244 )\r
5245{\r
5246 LIST_ENTRY *Link;\r
5247 FORMSET_STORAGE *Storage;\r
7c6c064c 5248 FORM_BROWSER_FORMSET *OldFormSet;\r
7936fb6a 5249\r
6e74560f
ED
5250 //\r
5251 // Try to find pre FormSet in the maintain backup list.\r
5252 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
5253 //\r
5254 OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
5255 if (OldFormSet != NULL) {\r
892eccc8 5256 SyncStatusForFormSet (FormSet, OldFormSet);\r
6e74560f
ED
5257 RemoveEntryList (&OldFormSet->Link);\r
5258 DestroyFormSet (OldFormSet);\r
5259 }\r
5260 InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
5261\r
1deb5cab
ED
5262 //\r
5263 // Extract default from IFR binary for no storage questions.\r
5264 // \r
787fc2a6 5265 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\r
1deb5cab 5266\r
7936fb6a 5267 //\r
5268 // Request current settings from Configuration Driver\r
5269 //\r
5270 Link = GetFirstNode (&FormSet->StorageListHead);\r
5271 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
5272 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
5273\r
7c6c064c 5274 LoadStorage (FormSet, Storage);\r
7936fb6a 5275\r
7936fb6a 5276 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
5277 }\r
7936fb6a 5278}\r
5279\r
5280\r
5281/**\r
5282 Fetch the Ifr binary data of a FormSet.\r
5283\r
5284 @param Handle PackageList Handle\r
f5006bd9 5285 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5286 specified (NULL or zero GUID), take the first\r
5287 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5288 found in package list.\r
5289 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5290 @param BinaryLength The length of the FormSet IFR binary.\r
5291 @param BinaryData The buffer designed to receive the FormSet.\r
5292\r
5293 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
5294 BufferLength was updated.\r
5295 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
5296 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
5297 be found with the requested FormId.\r
5298\r
5299**/\r
5300EFI_STATUS\r
5301GetIfrBinaryData (\r
5302 IN EFI_HII_HANDLE Handle,\r
5303 IN OUT EFI_GUID *FormSetGuid,\r
5304 OUT UINTN *BinaryLength,\r
5305 OUT UINT8 **BinaryData\r
5306 )\r
5307{\r
5308 EFI_STATUS Status;\r
5309 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
5310 UINTN BufferSize;\r
5311 UINT8 *Package;\r
5312 UINT8 *OpCodeData;\r
5313 UINT32 Offset;\r
5314 UINT32 Offset2;\r
7936fb6a 5315 UINT32 PackageListLength;\r
5316 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
5317 UINT8 Index;\r
5318 UINT8 NumberOfClassGuid;\r
f5006bd9 5319 BOOLEAN ClassGuidMatch;\r
0a1147ed 5320 EFI_GUID *ClassGuid;\r
f5006bd9 5321 EFI_GUID *ComparingGuid;\r
7936fb6a 5322\r
5323 OpCodeData = NULL;\r
5324 Package = NULL;\r
0c66bc76 5325 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 5326\r
5327 //\r
f5006bd9 5328 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 5329 //\r
48a9d5f7
LG
5330 if (FormSetGuid == NULL) {\r
5331 ComparingGuid = &gZeroGuid;\r
7936fb6a 5332 } else {\r
f5006bd9 5333 ComparingGuid = FormSetGuid;\r
7936fb6a 5334 }\r
5335\r
5336 //\r
5337 // Get HII PackageList\r
5338 //\r
5339 BufferSize = 0;\r
5340 HiiPackageList = NULL;\r
5341 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5342 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5343 HiiPackageList = AllocatePool (BufferSize);\r
5344 ASSERT (HiiPackageList != NULL);\r
5345\r
5346 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
5347 }\r
5348 if (EFI_ERROR (Status)) {\r
5349 return Status;\r
5350 }\r
db0bd81c 5351 ASSERT (HiiPackageList != NULL);\r
d66e6c16 5352\r
7936fb6a 5353 //\r
5354 // Get Form package from this HII package List\r
5355 //\r
5356 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
5357 Offset2 = 0;\r
5358 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
5359\r
f5006bd9 5360 ClassGuidMatch = FALSE;\r
7936fb6a 5361 while (Offset < PackageListLength) {\r
5362 Package = ((UINT8 *) HiiPackageList) + Offset;\r
5363 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
5364\r
8d00a0f1 5365 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 5366 //\r
5367 // Search FormSet in this Form Package\r
5368 //\r
5369 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
5370 while (Offset2 < PackageHeader.Length) {\r
5371 OpCodeData = Package + Offset2;\r
5372\r
5373 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
5374 //\r
f5006bd9 5375 // Try to compare against formset GUID\r
7936fb6a 5376 //\r
48a9d5f7
LG
5377 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
5378 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 5379 break;\r
7936fb6a 5380 }\r
5381\r
d228526f
LG
5382 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
5383 //\r
5384 // Try to compare against formset class GUID\r
5385 //\r
5386 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
5387 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
5388 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
5389 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
5390 ClassGuidMatch = TRUE;\r
5391 break;\r
5392 }\r
5393 }\r
5394 if (ClassGuidMatch) {\r
f5006bd9 5395 break;\r
5396 }\r
d228526f
LG
5397 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
5398 ClassGuidMatch = TRUE;\r
7936fb6a 5399 break;\r
5400 }\r
5401 }\r
5402\r
5403 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
5404 }\r
5405\r
5406 if (Offset2 < PackageHeader.Length) {\r
5407 //\r
5408 // Target formset found\r
5409 //\r
5410 break;\r
5411 }\r
5412 }\r
5413\r
5414 Offset += PackageHeader.Length;\r
5415 }\r
5416\r
5417 if (Offset >= PackageListLength) {\r
5418 //\r
5419 // Form package not found in this Package List\r
5420 //\r
f4113e1f 5421 FreePool (HiiPackageList);\r
7936fb6a 5422 return EFI_NOT_FOUND;\r
5423 }\r
5424\r
48a9d5f7 5425 if (FormSetGuid != NULL) {\r
7936fb6a 5426 //\r
f5006bd9 5427 // Return the FormSet GUID\r
7936fb6a 5428 //\r
5429 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
5430 }\r
5431\r
5432 //\r
5433 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
5434 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
5435 // of the Form Package.\r
5436 //\r
5437 *BinaryLength = PackageHeader.Length - Offset2;\r
5438 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
5439\r
f4113e1f 5440 FreePool (HiiPackageList);\r
7936fb6a 5441\r
5442 if (*BinaryData == NULL) {\r
5443 return EFI_OUT_OF_RESOURCES;\r
5444 }\r
5445\r
5446 return EFI_SUCCESS;\r
5447}\r
5448\r
5449\r
5450/**\r
5451 Initialize the internal data structure of a FormSet.\r
5452\r
5453 @param Handle PackageList Handle\r
f5006bd9 5454 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
5455 specified (NULL or zero GUID), take the first\r
5456 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
5457 found in package list.\r
5458 On output, GUID of the formset found(if not NULL).\r
7936fb6a 5459 @param FormSet FormSet data structure.\r
5460\r
5461 @retval EFI_SUCCESS The function completed successfully.\r
5462 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
5463\r
5464**/\r
5465EFI_STATUS\r
5466InitializeFormSet (\r
5467 IN EFI_HII_HANDLE Handle,\r
5468 IN OUT EFI_GUID *FormSetGuid,\r
7c6c064c 5469 OUT FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 5470 )\r
5471{\r
5472 EFI_STATUS Status;\r
5473 EFI_HANDLE DriverHandle;\r
7936fb6a 5474\r
5475 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
5476 if (EFI_ERROR (Status)) {\r
5477 return Status;\r
5478 }\r
5479\r
48a9d5f7 5480 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 5481 FormSet->HiiHandle = Handle;\r
5482 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
7c6c064c 5483 FormSet->QuestionInited = FALSE;\r
7936fb6a 5484\r
5485 //\r
5486 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
5487 //\r
5488 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
5489 if (EFI_ERROR (Status)) {\r
5490 return Status;\r
5491 }\r
5492 FormSet->DriverHandle = DriverHandle;\r
5493 Status = gBS->HandleProtocol (\r
5494 DriverHandle,\r
5495 &gEfiHiiConfigAccessProtocolGuid,\r
5496 (VOID **) &FormSet->ConfigAccess\r
5497 );\r
5498 if (EFI_ERROR (Status)) {\r
5499 //\r
5500 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
5501 // list, then there will be no configuration action required\r
5502 //\r
5503 FormSet->ConfigAccess = NULL;\r
5504 }\r
5505\r
5506 //\r
5507 // Parse the IFR binary OpCodes\r
5508 //\r
5509 Status = ParseOpCodes (FormSet);\r
25361615 5510\r
7c6c064c 5511 return Status;\r
7936fb6a 5512}\r
ce6d12cc 5513\r
5514\r
5515/**\r
5516 Save globals used by previous call to SendForm(). SendForm() may be called from \r
5517 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
5518 So, save globals of previous call to SendForm() and restore them upon exit.\r
5519\r
5520**/\r
5521VOID\r
5522SaveBrowserContext (\r
5523 VOID\r
5524 )\r
5525{\r
5526 BROWSER_CONTEXT *Context;\r
7c6c064c 5527 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 5528\r
5529 gBrowserContextCount++;\r
5530 if (gBrowserContextCount == 1) {\r
5531 //\r
5532 // This is not reentry of SendForm(), no context to save\r
5533 //\r
5534 return;\r
5535 }\r
5536\r
5537 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
5538 ASSERT (Context != NULL);\r
5539\r
5540 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
5541\r
5542 //\r
5543 // Save FormBrowser context\r
5544 //\r
5a9f73bf 5545 Context->Selection = gCurrentSelection;\r
ce6d12cc 5546 Context->ResetRequired = gResetRequired;\r
f2e7732e
ED
5547 Context->FlagReconnect = gFlagReconnect;\r
5548 Context->CallbackReconnect = gCallbackReconnect;\r
7c6c064c
ED
5549 Context->ExitRequired = gExitRequired;\r
5550 Context->HiiHandle = mCurrentHiiHandle;\r
5a9f73bf
ED
5551 Context->FormId = mCurrentFormId;\r
5552 CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
7c6c064c
ED
5553\r
5554 //\r
5555 // Save the menu history data.\r
5556 //\r
5557 InitializeListHead(&Context->FormHistoryList);\r
5558 while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
5559 MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
5560 RemoveEntryList (&MenuList->Link);\r
5561\r
5562 InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
5563 }\r
ce6d12cc 5564\r
5565 //\r
5566 // Insert to FormBrowser context list\r
5567 //\r
5568 InsertHeadList (&gBrowserContextList, &Context->Link);\r
5569}\r
5570\r
5571\r
5572/**\r
5573 Restore globals used by previous call to SendForm().\r
5574\r
5575**/\r
5576VOID\r
5577RestoreBrowserContext (\r
5578 VOID\r
5579 )\r
5580{\r
5581 LIST_ENTRY *Link;\r
5582 BROWSER_CONTEXT *Context;\r
7c6c064c 5583 FORM_ENTRY_INFO *MenuList;\r
ce6d12cc 5584\r
5585 ASSERT (gBrowserContextCount != 0);\r
5586 gBrowserContextCount--;\r
5587 if (gBrowserContextCount == 0) {\r
5588 //\r
5589 // This is not reentry of SendForm(), no context to restore\r
5590 //\r
5591 return;\r
5592 }\r
5593\r
5594 ASSERT (!IsListEmpty (&gBrowserContextList));\r
5595\r
5596 Link = GetFirstNode (&gBrowserContextList);\r
5597 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
5598\r
5599 //\r
5600 // Restore FormBrowser context\r
5601 //\r
5a9f73bf 5602 gCurrentSelection = Context->Selection;\r
ce6d12cc 5603 gResetRequired = Context->ResetRequired;\r
f2e7732e
ED
5604 gFlagReconnect = Context->FlagReconnect;\r
5605 gCallbackReconnect = Context->CallbackReconnect;\r
7c6c064c
ED
5606 gExitRequired = Context->ExitRequired;\r
5607 mCurrentHiiHandle = Context->HiiHandle;\r
5a9f73bf
ED
5608 mCurrentFormId = Context->FormId;\r
5609 CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
7c6c064c
ED
5610\r
5611 //\r
5612 // Restore the menu history data.\r
5613 //\r
5614 while (!IsListEmpty (&Context->FormHistoryList)) {\r
5615 MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
5616 RemoveEntryList (&MenuList->Link);\r
5617\r
5618 InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
5619 }\r
ce6d12cc 5620\r
5621 //\r
5622 // Remove from FormBrowser context list\r
5623 //\r
5624 RemoveEntryList (&Context->Link);\r
5625 gBS->FreePool (Context);\r
5626}\r
48a9d5f7
LG
5627\r
5628/**\r
5629 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
5630 \r
5631 @param Handle The Hii Handle.\r
5632 \r
5633 @return the found FormSet context. If no found, NULL will return.\r
5634\r
5635**/\r
5636FORM_BROWSER_FORMSET * \r
5637GetFormSetFromHiiHandle (\r
5638 EFI_HII_HANDLE Handle\r
5639 )\r
5640{\r
5641 LIST_ENTRY *Link;\r
5642 FORM_BROWSER_FORMSET *FormSet;\r
5643\r
5644 Link = GetFirstNode (&gBrowserFormSetList);\r
5645 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5646 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
5647 Link = GetNextNode (&gBrowserFormSetList, Link);\r
5648 if (!ValidateFormSet(FormSet)) {\r
5649 continue;\r
5650 }\r
48a9d5f7
LG
5651 if (FormSet->HiiHandle == Handle) {\r
5652 return FormSet;\r
5653 }\r
48a9d5f7
LG
5654 }\r
5655 \r
5656 return NULL;\r
5657}\r
5658\r
5659/**\r
5660 Check whether the input HII handle is the FormSet that is being used.\r
5661 \r
5662 @param Handle The Hii Handle.\r
5663 \r
5664 @retval TRUE HII handle is being used.\r
5665 @retval FALSE HII handle is not being used.\r
5666\r
5667**/\r
5668BOOLEAN\r
5669IsHiiHandleInBrowserContext (\r
5670 EFI_HII_HANDLE Handle\r
5671 )\r
5672{\r
5673 LIST_ENTRY *Link;\r
5674 BROWSER_CONTEXT *Context;\r
5675\r
5676 //\r
5677 // HiiHandle is Current FormSet.\r
5678 //\r
7c6c064c 5679 if (mCurrentHiiHandle == Handle) {\r
48a9d5f7
LG
5680 return TRUE;\r
5681 }\r
5682\r
5683 //\r
5684 // Check whether HiiHandle is in BrowserContext.\r
5685 //\r
5686 Link = GetFirstNode (&gBrowserContextList);\r
5687 while (!IsNull (&gBrowserContextList, Link)) {\r
5688 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
7c6c064c 5689 if (Context->HiiHandle == Handle) {\r
48a9d5f7
LG
5690 //\r
5691 // HiiHandle is in BrowserContext\r
5692 //\r
5693 return TRUE;\r
5694 }\r
5695 Link = GetNextNode (&gBrowserContextList, Link);\r
5696 }\r
5697 \r
5698 return FALSE;\r
5699}\r
5700\r
7c6c064c
ED
5701/**\r
5702 Perform Password check. \r
5703 Passwork may be encrypted by driver that requires the specific check.\r
5704 \r
5705 @param Form Form where Password Statement is in.\r
5706 @param Statement Password statement\r
5707 @param PasswordString Password string to be checked. It may be NULL.\r
5708 NULL means to restore password.\r
5709 "" string can be used to checked whether old password does exist.\r
5710 \r
5711 @return Status Status of Password check.\r
5712**/\r
5713EFI_STATUS\r
5714EFIAPI\r
5715PasswordCheck (\r
5716 IN FORM_DISPLAY_ENGINE_FORM *Form,\r
5717 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
5718 IN EFI_STRING PasswordString OPTIONAL\r
5719 )\r
5720{\r
5721 EFI_STATUS Status;\r
5722 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5723 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
5724 EFI_IFR_TYPE_VALUE IfrTypeValue;\r
5725 FORM_BROWSER_STATEMENT *Question;\r
5726\r
5727 ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
5728 Question = GetBrowserStatement(Statement);\r
5729 ASSERT (Question != NULL);\r
5730\r
5731 if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
5732 if (ConfigAccess == NULL) {\r
5733 return EFI_UNSUPPORTED;\r
5734 }\r
5735 } else {\r
5736 if (PasswordString == NULL) {\r
5737 return EFI_SUCCESS;\r
5738 } \r
27582c41
ED
5739\r
5740 //\r
5741 // Check whether has preexisted password.\r
5742 //\r
5743 if (PasswordString[0] == 0) {\r
5744 if (*((CHAR16 *) Question->BufferValue) == 0) {\r
5745 return EFI_SUCCESS;\r
5746 } else {\r
5747 return EFI_NOT_READY;\r
5748 }\r
5749 }\r
5750\r
5751 //\r
5752 // Check whether the input password is same as preexisted password.\r
5753 //\r
7c6c064c
ED
5754 if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
5755 return EFI_SUCCESS;\r
5756 } else {\r
5757 return EFI_NOT_READY;\r
5758 }\r
5759 }\r
5760 \r
5761 //\r
5762 // Prepare password string in HII database\r
5763 //\r
5764 if (PasswordString != NULL) {\r
5765 IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
5766 } else {\r
5767 IfrTypeValue.string = 0;\r
5768 }\r
5769\r
5770 //\r
5771 // Send password to Configuration Driver for validation\r
5772 //\r
5773 Status = ConfigAccess->Callback (\r
5774 ConfigAccess,\r
5775 EFI_BROWSER_ACTION_CHANGING,\r
5776 Question->QuestionId,\r
5777 Question->HiiValue.Type,\r
5778 &IfrTypeValue,\r
5779 &ActionRequest\r
5780 );\r
5781\r
5782 //\r
5783 // Remove password string from HII database\r
5784 //\r
5785 if (PasswordString != NULL) {\r
5786 DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
5787 }\r
5788\r
5789 return Status;\r
5790}\r
5791\r
48a9d5f7
LG
5792/**\r
5793 Find the registered HotKey based on KeyData.\r
5794 \r
5795 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5796 information for the hot key.\r
5797\r
5798 @return The registered HotKey context. If no found, NULL will return.\r
5799**/\r
5800BROWSER_HOT_KEY *\r
5801GetHotKeyFromRegisterList (\r
5802 IN EFI_INPUT_KEY *KeyData\r
5803 )\r
5804{\r
5805 LIST_ENTRY *Link;\r
5806 BROWSER_HOT_KEY *HotKey;\r
5807\r
5808 Link = GetFirstNode (&gBrowserHotKeyList);\r
5809 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
5810 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
5811 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
5812 return HotKey;\r
5813 }\r
5814 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
5815 }\r
5816 \r
5817 return NULL;\r
5818}\r
5819\r
5820/**\r
5821 Configure what scope the hot key will impact.\r
5822 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
5823 If no scope is set, the default scope will be FormSet level.\r
5824 After all registered hot keys are removed, previous Scope can reset to another level.\r
5825 \r
5826 @param[in] Scope Scope level to be set. \r
5827 \r
5828 @retval EFI_SUCCESS Scope is set correctly.\r
5829 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
5830 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
5831\r
5832**/\r
5833EFI_STATUS\r
5834EFIAPI\r
5835SetScope (\r
5836 IN BROWSER_SETTING_SCOPE Scope\r
5837 )\r
5838{\r
5839 if (Scope >= MaxLevel) {\r
5840 return EFI_INVALID_PARAMETER;\r
5841 }\r
7c6c064c 5842\r
48a9d5f7
LG
5843 //\r
5844 // When no hot key registered in system or on the first setting,\r
5845 // Scope can be set.\r
5846 //\r
5847 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
5848 gBrowserSettingScope = Scope;\r
5849 mBrowserScopeFirstSet = FALSE;\r
5850 } else if (Scope != gBrowserSettingScope) {\r
5851 return EFI_UNSUPPORTED;\r
5852 }\r
5853\r
5854 return EFI_SUCCESS;\r
5855}\r
5856\r
5857/**\r
5858 Register the hot key with its browser action, or unregistered the hot key.\r
5859 Only support hot key that is not printable character (control key, function key, etc.).\r
5860 If the action value is zero, the hot key will be unregistered if it has been registered.\r
5861 If the same hot key has been registered, the new action and help string will override the previous ones.\r
5862 \r
5863 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
5864 information for the hot key. Its type is EFI_INPUT_KEY to \r
5865 be supported by all ConsoleIn devices.\r
5866 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
5867 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
5868 @param[in] HelpString Help string that describes the hot key information.\r
5869 Its value may be NULL for the unregistered hot key.\r
5870 \r
5871 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
5872 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
5873 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
5874 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
5875**/\r
5876EFI_STATUS\r
5877EFIAPI\r
5878RegisterHotKey (\r
5879 IN EFI_INPUT_KEY *KeyData,\r
5880 IN UINT32 Action,\r
5881 IN UINT16 DefaultId,\r
5882 IN EFI_STRING HelpString OPTIONAL\r
5883 )\r
5884{\r
5885 BROWSER_HOT_KEY *HotKey;\r
5886\r
5887 //\r
5888 // Check input parameters.\r
5889 //\r
5890 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
5891 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
5892 return EFI_INVALID_PARAMETER;\r
5893 }\r
5894\r
5895 //\r
5896 // Check whether the input KeyData is in BrowserHotKeyList.\r
5897 //\r
5898 HotKey = GetHotKeyFromRegisterList (KeyData);\r
5899 \r
5900 //\r
5901 // Unregister HotKey\r
5902 //\r
5903 if (Action == BROWSER_ACTION_UNREGISTER) {\r
5904 if (HotKey != NULL) {\r
5905 //\r
5906 // The registered HotKey is found. \r
5907 // Remove it from List, and free its resource.\r
5908 //\r
5909 RemoveEntryList (&HotKey->Link);\r
5910 FreePool (HotKey->KeyData);\r
5911 FreePool (HotKey->HelpString);\r
5912 return EFI_SUCCESS;\r
5913 } else {\r
5914 //\r
5915 // The registered HotKey is not found. \r
5916 //\r
5917 return EFI_NOT_FOUND;\r
5918 }\r
5919 }\r
5920 \r
5921 //\r
5922 // Register HotKey into List.\r
5923 //\r
5924 if (HotKey == NULL) {\r
5925 //\r
5926 // Create new Key, and add it into List.\r
5927 //\r
5928 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
5929 ASSERT (HotKey != NULL);\r
5930 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
5931 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
5932 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
5933 }\r
5934\r
5935 //\r
5936 // Fill HotKey information.\r
5937 //\r
5938 HotKey->Action = Action;\r
5939 HotKey->DefaultId = DefaultId;\r
5940 if (HotKey->HelpString != NULL) {\r
5941 FreePool (HotKey->HelpString);\r
5942 }\r
5943 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
5944\r
5945 return EFI_SUCCESS;\r
5946}\r
5947\r
5948/**\r
5949 Register Exit handler function. \r
5950 When more than one handler function is registered, the latter one will override the previous one. \r
5951 When NULL handler is specified, the previous Exit handler will be unregistered. \r
5952 \r
5953 @param[in] Handler Pointer to handler function. \r
5954\r
5955**/\r
5956VOID\r
5957EFIAPI\r
5958RegiserExitHandler (\r
5959 IN EXIT_HANDLER Handler\r
5960 )\r
5961{\r
5962 ExitHandlerFunction = Handler;\r
5963 return;\r
5964}\r
5965\r
7c6c064c
ED
5966/**\r
5967 Check whether the browser data has been modified.\r
5968\r
5969 @retval TRUE Browser data is modified.\r
5970 @retval FALSE No browser data is modified.\r
5971\r
5972**/\r
5973BOOLEAN\r
5974EFIAPI\r
5975IsBrowserDataModified (\r
5976 VOID\r
5977 )\r
5978{\r
5979 LIST_ENTRY *Link;\r
5980 FORM_BROWSER_FORMSET *FormSet;\r
5981\r
7c6c064c
ED
5982 switch (gBrowserSettingScope) {\r
5983 case FormLevel:\r
27bace9b
ED
5984 if (gCurrentSelection == NULL) {\r
5985 return FALSE;\r
5986 }\r
7c6c064c
ED
5987 return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
5988\r
5989 case FormSetLevel:\r
27bace9b
ED
5990 if (gCurrentSelection == NULL) {\r
5991 return FALSE;\r
5992 }\r
7c6c064c
ED
5993 return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
5994\r
5995 case SystemLevel:\r
5996 Link = GetFirstNode (&gBrowserFormSetList);\r
5997 while (!IsNull (&gBrowserFormSetList, Link)) {\r
5998 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
27bace9b
ED
5999 if (!ValidateFormSet(FormSet)) {\r
6000 continue;\r
6001 }\r
6002\r
7c6c064c
ED
6003 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
6004 return TRUE;\r
6005 }\r
6006 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6007 }\r
6008 return FALSE;\r
6009\r
6010 default:\r
6011 return FALSE;\r
6012 }\r
6013}\r
6014\r
6015/**\r
6016 Execute the action requested by the Action parameter.\r
6017\r
6018 @param[in] Action Execute the request action.\r
6019 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
6020\r
6021 @retval EFI_SUCCESS Execute the request action succss.\r
6022 @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
6023\r
6024**/\r
6025EFI_STATUS \r
6026EFIAPI\r
6027ExecuteAction (\r
6028 IN UINT32 Action,\r
6029 IN UINT16 DefaultId\r
6030 )\r
6031{\r
27bace9b
ED
6032 EFI_STATUS Status;\r
6033 FORM_BROWSER_FORMSET *FormSet;\r
6034 FORM_BROWSER_FORM *Form;\r
7c6c064c 6035\r
27bace9b 6036 if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {\r
7c6c064c
ED
6037 return EFI_NOT_READY;\r
6038 }\r
6039\r
27bace9b
ED
6040 Status = EFI_SUCCESS;\r
6041 FormSet = NULL;\r
6042 Form = NULL;\r
6043 if (gBrowserSettingScope < SystemLevel) {\r
6044 FormSet = gCurrentSelection->FormSet;\r
6045 Form = gCurrentSelection->Form; \r
6046 }\r
7c6c064c
ED
6047\r
6048 //\r
6049 // Executet the discard action.\r
6050 //\r
6051 if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
27bace9b 6052 Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6053 if (EFI_ERROR (Status)) {\r
6054 return Status;\r
6055 }\r
6056 }\r
6057\r
6058 //\r
6059 // Executet the difault action.\r
6060 //\r
6061 if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
787fc2a6 6062 Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
7c6c064c
ED
6063 if (EFI_ERROR (Status)) {\r
6064 return Status;\r
6065 }\r
892eccc8 6066 UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6067 }\r
6068\r
6069 //\r
6070 // Executet the submit action.\r
6071 //\r
6072 if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
27bace9b 6073 Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6074 if (EFI_ERROR (Status)) {\r
6075 return Status;\r
6076 }\r
6077 }\r
6078\r
6079 //\r
6080 // Executet the reset action.\r
6081 //\r
6082 if ((Action & BROWSER_ACTION_RESET) != 0) {\r
6083 gResetRequired = TRUE;\r
6084 }\r
6085\r
6086 //\r
6087 // Executet the exit action.\r
6088 //\r
6089 if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
27bace9b 6090 DiscardForm (FormSet, Form, gBrowserSettingScope);\r
7c6c064c
ED
6091 if (gBrowserSettingScope == SystemLevel) {\r
6092 if (ExitHandlerFunction != NULL) {\r
6093 ExitHandlerFunction ();\r
6094 }\r
6095 }\r
6096\r
6097 gExitRequired = TRUE;\r
6098 }\r
6099\r
6100 return Status;\r
6101}\r
6102\r
48a9d5f7
LG
6103/**\r
6104 Create reminder to let user to choose save or discard the changed browser data.\r
6105 Caller can use it to actively check the changed browser data.\r
6106\r
6107 @retval BROWSER_NO_CHANGES No browser data is changed.\r
6108 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
6109 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
27bace9b 6110 @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
48a9d5f7
LG
6111\r
6112**/\r
6113UINT32\r
6114EFIAPI\r
6115SaveReminder (\r
6116 VOID\r
6117 )\r
6118{\r
6119 LIST_ENTRY *Link;\r
6120 FORM_BROWSER_FORMSET *FormSet;\r
6121 BOOLEAN IsDataChanged;\r
6122 UINT32 DataSavedAction;\r
27bace9b 6123 UINT32 ConfirmRet;\r
48a9d5f7
LG
6124\r
6125 DataSavedAction = BROWSER_NO_CHANGES;\r
6126 IsDataChanged = FALSE;\r
6127 Link = GetFirstNode (&gBrowserFormSetList);\r
6128 while (!IsNull (&gBrowserFormSetList, Link)) {\r
6129 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
938baa1f
ED
6130 Link = GetNextNode (&gBrowserFormSetList, Link);\r
6131 if (!ValidateFormSet(FormSet)) {\r
6132 continue;\r
6133 }\r
7c6c064c 6134 if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
48a9d5f7
LG
6135 IsDataChanged = TRUE;\r
6136 break;\r
6137 }\r
48a9d5f7
LG
6138 }\r
6139 \r
6140 //\r
6141 // No data is changed. No save is required. \r
6142 //\r
6143 if (!IsDataChanged) {\r
6144 return DataSavedAction;\r
6145 }\r
6146 \r
6147 //\r
7c6c064c 6148 // If data is changed, prompt user to save or discard it. \r
48a9d5f7 6149 //\r
48a9d5f7 6150 do {\r
27bace9b 6151 ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();\r
48a9d5f7 6152\r
27bace9b 6153 if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
7c6c064c 6154 SubmitForm (NULL, NULL, SystemLevel);\r
27bace9b 6155 DataSavedAction = BROWSER_SAVE_CHANGES;\r
7c6c064c 6156 break;\r
27bace9b 6157 } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
7c6c064c 6158 DiscardForm (NULL, NULL, SystemLevel);\r
27bace9b
ED
6159 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
6160 break;\r
6161 } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
6162 DataSavedAction = BROWSER_KEEP_CURRENT;\r
7c6c064c
ED
6163 break;\r
6164 }\r
6165 } while (1);\r
48a9d5f7
LG
6166\r
6167 return DataSavedAction;\r
6168}\r
7da62bc0
ED
6169\r
6170/**\r
6171 Check whether the Reset Required for the browser\r
6172\r
6173 @retval TRUE Browser required to reset after exit.\r
6174 @retval FALSE Browser not need to reset after exit.\r
6175\r
6176**/\r
6177BOOLEAN\r
6178EFIAPI\r
6179IsResetRequired (\r
6180 VOID\r
6181 )\r
6182{\r
6183 return gResetRequired;\r
6184}\r
6185\r