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