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